简体   繁体   中英

Organising Data using Nested Generics in Java(Android)

I am creating a music player app. I retrieve the data from the directory in a class named SongInfo which looks like this:

public class SongInfo {

//id of song
private long _ID;

//song name
private String title;

//artist name
private String artistName;

//album name
private String albumName;

//song duration
long  duration;

//year of release
private String year;

//constructor

//comparators to sort data

My app has a structure such that there is a

ArtistsFragment to show the List of Artists on clicking -> it Opens up Albums Fragment which has the List of Albums of the selected artist -> opens up Songs Fragment which has ArrayList of Songs of the selected album. What I end up doing instead is create a data structure of this sort:

//contains most of the info of the song
ArrayList<SongInfo> songs;

//contains an arrayList of songs  
ArrayList<ArrayList<SongInfo>> albums;

//contains an arraylist of albums    
Arraylist<ArrayList<ArrayList<SongInfo>>> artists; 

which I am very sure is the wrong way to do it, cos what if I had more layers? I am looking for a better way to do this. I just need a hint, but an illustration/explanation would be awesome. Thanks :)

Suppose we start with these classes:

public static class Song
{
    String title;
    Artist artist;
    Album album;
    Song( String title, Artist artist, Album album ) 
        { this.title = title; this.artist = artist; this.album = album; }
    @Override public String toString() { return "Song: " + title; }
}

public static class Artist
{
    String name;
    Artist( String name ) { this.name = name; }
    @Override public String toString() { return "Artist: " + name; }
}

public static class Album
{
    String name;
    Album( String name ) { this.name = name; }
    @Override public String toString() { return "Album: " + name; }
}

Where:

  • Song is what you are now calling with the rather unfortunate name SongInfo
  • Artist is a class that you don't have yet, but you should. If you can't handle that, then whenever you see Artist just think of a String with an artist's name in it.
  • Album is another class that you don't have yet, but you should. If you can't handle that, then whenever you see Album just think of a String with an album's title in it.

And suppose we start with this dataset:

    Artist artist1 = new Artist( "Artist1" );
    Artist artist2 = new Artist( "Artist2" );
    Set<Artist> artists = new HashSet<>( Arrays.asList( artist1, artist2 ) );
    Album album1 = new Album( "Album1" );
    Album album2 = new Album( "Album2" );
    Set<Album> albums = new HashSet<>( Arrays.asList( album1, album2 ) );
    Song song11a = new Song( "Song11a", artist1, album1 );
    Song song11b = new Song( "Song11b", artist1, album1 );
    Song song22a = new Song( "Song22a", artist2, album2 );
    Song song22b = new Song( "Song22b", artist2, album2 );
    List<Song> songs = Arrays.asList( song11a, song11b, song22a, song22b );

Then the following will give you what you want:

Collection<Song> getSongsByArtist( Collection<Song> songs, Artist artist )
{
    return songs.stream().filter( song -> song.artist == artist )
        .collect( Collectors.toList() );
}

Collection<Album> getAlbumsByArtist( Collection<Song> songs, Artist artist )
{
    return songs.stream().filter( song -> song.artist == artist )
        .map( song -> song.album ).collect( Collectors.toSet() );
}

And the following will give you everything you always wanted to know about your dataset but were afraid to ask:

Map<Song,Artist> artistsBySong = songs.stream()
    .collect( Collectors.toMap( Function.identity(), song -> song.artist ) );
Map<Song,Album> albumsBySong = songs.stream()
    .collect( Collectors.toMap( Function.identity(), song -> song.album ) );
Map<Artist,List<Song>> songsByArtist = songs.stream()
    .collect( Collectors.groupingBy( song -> song.artist ) );
Map<Album,List<Song>> songsByAlbum = songs.stream()
    .collect( Collectors.groupingBy( song -> song.album ) );
assert songs.stream().map( song -> song.album )
    .collect( Collectors.toSet() ).equals( albums );
assert songsByAlbum.keySet().equals( albums );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM