Java 对象+;列表中的对象列表?

Java 对象+;列表中的对象列表?,java,list,Java,List,我有一件有趣又麻烦的任务要解决。 我需要创建一个播放列表(某种列表),其中包含歌曲和其他子播放列表的歌曲。。。每个播放列表都有播放模式(随机、顺序等)。是否可以创建这样的播放列表? 我考虑过破解子播放列表,并将其中的扩展歌曲添加到主播放列表中,或者为添加到主播放列表中的每首歌曲创建一个子播放列表(我真的不喜欢这个想法) 不知何故,它绕过了这个问题,但有必要保持播放模式的每个播放列表 例如: 主播放列表(序列palymode)具有: (1) 歌曲1-1/ (2) 具有随机播放模式的子播放列表(歌曲

我有一件有趣又麻烦的任务要解决。 我需要创建一个播放列表(某种列表),其中包含歌曲和其他子播放列表的歌曲。。。每个播放列表都有播放模式(随机、顺序等)。是否可以创建这样的播放列表? 我考虑过破解子播放列表,并将其中的扩展歌曲添加到主播放列表中,或者为添加到主播放列表中的每首歌曲创建一个子播放列表(我真的不喜欢这个想法) 不知何故,它绕过了这个问题,但有必要保持播放模式的每个播放列表

例如:

主播放列表(序列palymode)具有: (1) 歌曲1-1/ (2) 具有随机播放模式的子播放列表(歌曲2-1、歌曲2-2、歌曲2-3)/ (3) 歌曲1-2

预期结果: (1) 歌曲1-1/ (2) 歌曲2-3(开始随机子播放列表)/ (3) 歌曲2-1/ (4) 歌曲2-2/ (5) 歌曲1-2/


我应该如何处理这个问题?

方法1: 创建一个名为playlist和playlist项的类,该类可以保存SongID列表,该列表可以保存来自不同播放列表或歌曲ID的一组歌曲

class PlayList{
  List<PlayListItem> playlistItems;
}

class PlayListItem{
  List<String> songIds;
}
class播放列表{
列出播放列表项目;
}
类播放项{
列出SongID;
}
这有助于识别通过特定子播放列表添加的歌曲集。然而,与方法2相比,这种方法使得迭代稍微困难一些

方法2: 这里,在播放列表项中避免了列表,因此显示播放列表时的迭代非常简单。但是,要识别通过特定子播放列表添加的SongID列表,必须计算

class PlayList{
  List<PlayListItem> playlistItems;
}
class PlayListItem{
  String songId;
  String referencePlayListId;
}
class播放列表{
列出播放列表项目;
}
类播放项{
字符串songId;
字符串referencePlayListId;
}

方法1: 创建一个名为playlist和playlist项的类,该类可以保存SongID列表,该列表可以保存来自不同播放列表或歌曲ID的一组歌曲

class PlayList{
  List<PlayListItem> playlistItems;
}

class PlayListItem{
  List<String> songIds;
}
class播放列表{
列出播放列表项目;
}
类播放项{
列出SongID;
}
这有助于识别通过特定子播放列表添加的歌曲集。然而,与方法2相比,这种方法使得迭代稍微困难一些

方法2: 这里,在播放列表项中避免了列表,因此显示播放列表时的迭代非常简单。但是,要识别通过特定子播放列表添加的SongID列表,必须计算

class PlayList{
  List<PlayListItem> playlistItems;
}
class PlayListItem{
  String songId;
  String referencePlayListId;
}
class播放列表{
列出播放列表项目;
}
类播放项{
字符串songId;
字符串referencePlayListId;
}

因为我怀疑这是一个家庭作业,所以我只提供一个部分实现,让您知道如何继续

创建一个抽象类
playline元素
,它可以是一首
歌曲
,也可以是另一个
播放列表

abstract class PlaylistElement {
    public abstract List<Song> printSongs();
}
实现一个类
歌曲
扩展
播放元素

class Playlist extends PlaylistElement {
    private List<PlaylistElement> elements;
    private PlaybackMode playbackMode;
    @Override
    public List<Song> printSongs() {
        if(this.playbackMode == PlaybackMode.RANDOM) {
            List<Song> songs = new ArrayList<>();
            List<PlaylistElement> shuffleElements = new ArrayList<>();

            //Add all PlaylistElements from elements into shuffleElements
            //and shuffle the shuffleElements collection

            //insert your songs into the songs collection here by sequentially
            //going through your
            //PlaylistElements and inserting the result of their printSongs()
            //implementation (e.g. in a for-loop)

            return songs;
        }
        else if(this.playbackMode == PlaybackMode.SEQUENTIAL) {
            //you can do this on your own
        }
        return null;
    }
}
class Song extends PlaylistElement {
    private String title;
    private String artist;
    .
    .
    .
    @Override
    public List<Song> printSongs() {
        //return a List with only this Song instance inside
        return Arrays.asList(new Song[] { this });
    }
}

希望这能给你一个大概的想法!为了简洁起见,省略了getter/setter和其他重要部分。

因为我怀疑这是一个家庭作业,所以我只提供部分实现,以便您了解如何继续

创建一个抽象类
playline元素
,它可以是一首
歌曲
,也可以是另一个
播放列表

abstract class PlaylistElement {
    public abstract List<Song> printSongs();
}
实现一个类
歌曲
扩展
播放元素

class Playlist extends PlaylistElement {
    private List<PlaylistElement> elements;
    private PlaybackMode playbackMode;
    @Override
    public List<Song> printSongs() {
        if(this.playbackMode == PlaybackMode.RANDOM) {
            List<Song> songs = new ArrayList<>();
            List<PlaylistElement> shuffleElements = new ArrayList<>();

            //Add all PlaylistElements from elements into shuffleElements
            //and shuffle the shuffleElements collection

            //insert your songs into the songs collection here by sequentially
            //going through your
            //PlaylistElements and inserting the result of their printSongs()
            //implementation (e.g. in a for-loop)

            return songs;
        }
        else if(this.playbackMode == PlaybackMode.SEQUENTIAL) {
            //you can do this on your own
        }
        return null;
    }
}
class Song extends PlaylistElement {
    private String title;
    private String artist;
    .
    .
    .
    @Override
    public List<Song> printSongs() {
        //return a List with only this Song instance inside
        return Arrays.asList(new Song[] { this });
    }
}

希望这能给你一个大概的想法!为了简洁起见,省略了getter/setter和其他重要部分。

尽管已经有了一些答案,但我承诺提供一个示例实现。从开始,我们有一个公共接口
可播放
,它是为复合设计模式实现的类

public interface Playable {
    String getSongName();
}
接下来,使用
Song
类来表示一首歌曲

public class Song implements Playable {

    private String name;

    public Song(String name) {
        this.name = name;
    }

    @Override
    public String getSongName() {
        return name;
    }
}
在准备播放列表时,请使用枚举来表示不同的播放模式

public enum PlayingMode {
    SEQUENCE, RANDOM
}
现在,最后是播放列表类

public class Playlist implements Playable {

    private String name;
    private List<Playable> playables = new ArrayList<>();
    private PlayingMode mode;

    private Playable currentItem;
    private List<Playable> next = new ArrayList<>();

    public Playlist(String name, PlayingMode mode) {
        this.name = name;
        this.mode = mode;
    }

    @Override
    public String getSongName() {
        if (playables.isEmpty()) {
            return null;
        }

        if (currentItem == null) {
            // initialize the playing songs
            next.addAll(playables);
            if (mode == PlayingMode.RANDOM) {
                Collections.shuffle(next);
            }
            currentItem = next.get(0);
        } else {
            // if we have a playlist, play its songs first
            if (currentItem instanceof Playlist) {
                String candidate = currentItem.getSongName();
                if (candidate != null) {
                    return candidate;
                }
            }

            int index = next.indexOf(currentItem);
            index++;
            if (index < next.size()) {
                currentItem = next.get(index);
            } else {
                currentItem = null;
            }
        }

        return currentItem != null ? currentItem.getSongName() : null;
    }

    private void addToNext(Playable playable) {
        if (currentItem == null) {
            return;
        }

        // if the playlist is playing, add it to those list as well
        if (mode == PlayingMode.SEQUENCE) {
            next.add(playable);
        } else if (mode == PlayingMode.RANDOM) {
            int currentIndex = next.indexOf(currentItem);
            int random = ThreadLocalRandom.current().nextInt(currentIndex, next.size());
            next.add(random, playable);
        }
    }

    public void addPlayable(Playable playable) {
        Objects.requireNonNull(playable);
        playables.add(playable);
        addToNext(playable);
    }
}
可以给出以下输出:

Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song C
Current song is: Song 3
您还可以在播放时添加歌曲:

while (songName != null) {
    System.out.println("Current song is: " + songName);
    songName = main.getSongName();

    // add songs while playing
    if ("Song A".equals(songName)) {
        subPlaylist1.addPlayable(new Song("Song D"));
        subPlaylist1.addPlayable(new Song("Song E"));
        subPlaylist1.addPlayable(new Song("Song F"));
    }
}
这可能导致:

Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song E
Current song is: Song D
Current song is: Song F
Current song is: Song C
Current song is: Song 3
最后的一些注意事项:

  • getIndex
    方法的最坏运行时间为O(n),如果播放列表中有许多歌曲,这可能是一个问题。更快的
    收集
    设置
    映射
    将提供更好的性能,但实现要复杂一些
  • 这些类已经简化,这意味着为了简洁起见,省略了一些getter和setter以及equals和hashCode

尽管已经有了一些答案,但我承诺会提供一个示例实现。从开始,我们有一个公共接口
可播放
,它是为复合设计模式实现的类

public interface Playable {
    String getSongName();
}
接下来,使用
Song
类来表示一首歌曲

public class Song implements Playable {

    private String name;

    public Song(String name) {
        this.name = name;
    }

    @Override
    public String getSongName() {
        return name;
    }
}
在准备播放列表时,请使用枚举来表示不同的播放模式

public enum PlayingMode {
    SEQUENCE, RANDOM
}
现在,最后是播放列表类

public class Playlist implements Playable {

    private String name;
    private List<Playable> playables = new ArrayList<>();
    private PlayingMode mode;

    private Playable currentItem;
    private List<Playable> next = new ArrayList<>();

    public Playlist(String name, PlayingMode mode) {
        this.name = name;
        this.mode = mode;
    }

    @Override
    public String getSongName() {
        if (playables.isEmpty()) {
            return null;
        }

        if (currentItem == null) {
            // initialize the playing songs
            next.addAll(playables);
            if (mode == PlayingMode.RANDOM) {
                Collections.shuffle(next);
            }
            currentItem = next.get(0);
        } else {
            // if we have a playlist, play its songs first
            if (currentItem instanceof Playlist) {
                String candidate = currentItem.getSongName();
                if (candidate != null) {
                    return candidate;
                }
            }

            int index = next.indexOf(currentItem);
            index++;
            if (index < next.size()) {
                currentItem = next.get(index);
            } else {
                currentItem = null;
            }
        }

        return currentItem != null ? currentItem.getSongName() : null;
    }

    private void addToNext(Playable playable) {
        if (currentItem == null) {
            return;
        }

        // if the playlist is playing, add it to those list as well
        if (mode == PlayingMode.SEQUENCE) {
            next.add(playable);
        } else if (mode == PlayingMode.RANDOM) {
            int currentIndex = next.indexOf(currentItem);
            int random = ThreadLocalRandom.current().nextInt(currentIndex, next.size());
            next.add(random, playable);
        }
    }

    public void addPlayable(Playable playable) {
        Objects.requireNonNull(playable);
        playables.add(playable);
        addToNext(playable);
    }
}
可以给出以下输出:

Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song C
Current song is: Song 3
您还可以在播放时添加歌曲:

while (songName != null) {
    System.out.println("Current song is: " + songName);
    songName = main.getSongName();

    // add songs while playing
    if ("Song A".equals(songName)) {
        subPlaylist1.addPlayable(new Song("Song D"));
        subPlaylist1.addPlayable(new Song("Song E"));
        subPlaylist1.addPlayable(new Song("Song F"));
    }
}
这可能导致:

Current song is: Song 1
Current song is: Song 2
Current song is: Song B
Current song is: Song A
Current song is: Song E
Current song is: Song D
Current song is: Song F
Current song is: Song C
Current song is: Song 3
最后的一些注意事项:

  • getIndex
    方法的最坏运行时间为O(n),如果播放列表中有许多歌曲,这可能是一个问题。更快的
    收集
    设置
    映射
    将提供更好的性能,但实现要复杂一些
  • 这些类已经简化,这意味着为了简洁起见,省略了一些getter和setter以及equals和hashCode

的确很有趣。到目前为止你试过什么?听起来像是家庭作业,太宽泛了,因为没有人试图解决它。老实说,我完全停留在概念步骤本身。。。我在管理收藏和模拟这样的播放列表播放器方面没有问题。我不知道如何提供一个现有的子播放列表,那么复合设计模式呢?你有一个播放列表和一首歌作为叶子。播放列表