我试图从我的 Spotify 收听历史记录下载中查找并找到播放次数最多的歌曲,下面的代码使用 99% 的 cpu 持续 20 秒,然后失败,并显示“线程“main”中的异常 java.lang.OutOfMemoryError: Java”堆空间”。
我希望它根据听过的总毫秒数为我提供我最常听的歌曲。我使用 arraylists 并使用自己的构造函数创建了一个名为“Song”的类,以便更轻松地包含我想要从 json 文件中获取的歌曲的所有信息。 json 文件结构和我的 2 个类如下。如果有帮助的话我使用 eclipse 23-09。 json 文件大小约为 23mb,有 23785257 个字符。
主要课程:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class MainTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
JSONParser jsonParser = new JSONParser();
ArrayList<Song> songs = new ArrayList<>();
Song mostPlayed = null;
Song mostTimesPlayed = null;
//ArrayList<Song> highlights = new ArrayList<>();
long maxLong = 0;
int maxPlays = 0;
try {
JSONArray jsonArray = (JSONArray) jsonParser.parse(new FileReader("C:\\Users\\Username\\eclipse-workspace\\csh\\csh\\history.json"));
Iterator<Object> iterator = jsonArray.iterator();
while (iterator.hasNext()) {
JSONObject jsonObject = (JSONObject) iterator.next();
String tempTrack = (String) jsonObject.get("master_metadata_track_name");
String tempAlbum = (String) jsonObject.get("master_metadata_album_album_name");
String tempArtist = (String) jsonObject.get("master_metadata_album_artist_name");
long tempLong = (long) jsonObject.get("ms_played");
if (songs.isEmpty() /*|| tempLong >=30000*/) {
songs.add(new Song(tempTrack, tempAlbum, tempArtist, tempLong));
}
else{
for (int i = 0; i < songs.size(); i++) {
if (( songs.get(i)).getTrackName() == tempTrack /*&& tempLong >=30000*/) {
(songs.get(i)).updateSong(tempLong);
}
else {
songs.add(new Song(tempTrack, tempAlbum, tempArtist, tempLong));
}
}
}
}
for (int i = 0; i < songs.size(); i++) {
if ((songs.get(i)).getTotalPlayedFor()> maxLong) {
mostPlayed = songs.get(i);
}
if ((songs.get(i)).getTotalPlayedFor()> maxPlays) {
mostTimesPlayed = songs.get(i);
}
}
System.out.println("――――――――――― Highlights ―――――――――――");
double maxTimeSec = mostPlayed.getTotalPlayedFor()/1000.0;
double maxTimeMin = maxTimeSec/60.0;
double maxTimeHr = maxTimeMin/60.0;
System.out.println("Most listened to song by time: ");
System.out.println("Song Name: " + mostPlayed.getTrackName());
System.out.println("By: " + mostPlayed.getArtist());
System.out.println("Playtime(ms): " + mostPlayed.getTotalPlayedFor());
System.out.println("Playtime(s): " + maxTimeSec);
System.out.println("Playtime(m): " + maxTimeMin);
System.out.println("Playtime(hr): " + maxTimeHr);
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (ParseException e) {
e.printStackTrace();
}
}
}
歌曲类:
public class Song {
private String trackName;
private String album;
private String artist;
private int timesPlayed;
private long totalPlayedFor;
/**
* @return the album
*/
public String getAlbum() {
return album;
}
public String getTrackName() {
return trackName;
}
public long getTotalPlayedFor() {
return totalPlayedFor;
}
public String getArtist() {
return artist;
}
public int getTimesPlayed() {
return timesPlayed;
}
public Song(String trackName, String album, String artist, long playedFor) {
this.trackName = trackName;
this.album = album;
this.artist = artist;
this.timesPlayed = 1;
totalPlayedFor = playedFor;
}
public void updateSong(long playedFor) {
timesPlayed = getTimesPlayed() + 1;
totalPlayedFor = getTotalPlayedFor() + playedFor;
}
}
文件中的 json 对象示例:
{
"ts": "2021-04-21T07:22:32Z",
"username": "USERNAME",
"platform": "Windows 10 (10.0.19042; x64)",
"ms_played": 0,
"conn_country": "COUNTRYCODE",
"ip_addr_decrypted": "IPADDRESS",
"user_agent_decrypted": "unknown",
"master_metadata_track_name": "Little Dark Age",
"master_metadata_album_artist_name": "MGMT",
"master_metadata_album_album_name": "Little Dark Age",
"spotify_track_uri": "spotify:track:2Y0iGXY6m6immVb2ktbseM",
"episode_name": null,
"episode_show_name": null,
"spotify_episode_uri": null,
"reason_start": "playbtn",
"reason_end": "endplay",
"shuffle": false,
"skipped": null,
"offline": false,
"offline_timestamp": 1618989748702,
"incognito_mode": false
}
如有任何帮助,我们将不胜感激!!
for循环内存在逻辑问题。
for (int i = 0; i < songs.size(); i++) {
if (( songs.get(i)).getTrackName() == tempTrack) {
(songs.get(i)).updateSong(tempLong);
}
else {
songs.add(new Song(tempTrack, tempAlbum, tempArtist, tempLong));
}
}
要比较
String
,请使用 equals()
。
for循环永远不会结束。因为每次
songs.add()
,数组大小都会立即增加。
这应该有效...
int i;
for (i = songs.size() - 1; i >= 0; i--) {
if (songs.get(i).getTrackName().equals(tempTrack)) {
break;
}
}
if (i >= 0) {
songs.get(i).updateSong(tempLong);
} else {
songs.add(new Song(tempTrack, tempAlbum, tempArtist, tempLong));
}