我试图获得一个歌曲列表的艺术家的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;
}
}
提前致谢。
答案 0 :(得分:1)
要提高效果,请将artists
从ArrayList<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命名约定是字段名称以小写字母开头,因此上面的第二个解决方案已更改以反映该内容。