优化循环

时间:2018-06-06 21:57:18

标签: java list optimization arraylist set

我试图获得一个歌曲列表的艺术家的ArrayList(或Set,或类似的东西)。每首歌都有getArtists功能,它返回一个参与歌曲的每个艺术家的数组 我们的目标是拥有一个艺术家名单,每个艺术家都应该有一个列表(或套装,以较快者为准),其中包含他参与的所有歌曲。

  

我的代码有效,但速度相当慢(1600首歌需要5秒)。我怎样才能加快速度呢?

我的代码

private ArrayList<Artist> getArtistsFromSongs(List<Song> songs)
{
    long start = System.currentTimeMillis();

    ArrayList<Artist> artists = new ArrayList<>();
    for (Song song : songs)
    {
        String[] artistsStringArray = song.getArtists();
        for (String artistString : artistsStringArray)
        {
            boolean artistAlreadyExists = false;
            int heExistsAt = -1;

            for (int i = 0; i < artists.size(); i++)
            {
                if (artists.get(i).name.equals(artistString))
                {
                    artistAlreadyExists = true;
                    heExistsAt = i;
                }
            }
            if (artistAlreadyExists)
            {
                artists.get(heExistsAt).songs.add(song);
            } else
            {
                Artist newArtist = new Artist(artistString, new ArrayList<>());
                newArtist.songs.add(song);
                artists.add(newArtist);
            }
        }
    }
    long test = System.currentTimeMillis() - start; //~5500 milliseconds
    return artists;
}

班级

class Artist
{
    public final String name;
    public final ArrayList<Song> songs;

    Artist(String name, ArrayList<Song> songs)
    {
        this.name = name;
        this.songs = songs;
    }
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

要提高效果,请将artistsArrayList<Artist>更改为HashMap<String, Artist>

通过这种方式,您可以使用快速简单的地图查找替换最里面的顺序搜索循环。

Map<String, Artist> artists = new HashMap<>();
for (Song song : songs) {
    for (String artistName : song.getArtists()) {
        Artist artist = artists.get(artistName);
        if (artist == null) {
            artist = new Artist(artistName, new ArrayList<>());
            artists.put(artistName, artist);
        }
        artist.Songs.add(song);
    }
}

在Java 8+中可以改进,特别是如果你稍微更改Artist类。

Map<String, Artist> artists = new HashMap<>();
for (Song song : songs) {
    for (String artistName : song.getArtists()) {
        artists.computeIfAbsent(artistName, Artist::new).addSong(song);
    }
}
class Artist {
    public final String name;
    public final ArrayList<Song> songs = new ArrayList<>();

    Artist(String name) {
        this.name = name;
    }

    void addSong(Song song) {
        this.songs.add(song);
    }
}

注意:Java命名约定是字段名称以小写字母开头,因此上面的第二个解决方案已更改以反映该内容。