如何优化从文件中搜索json数组

问题描述 投票:0回答:1

我试图从我的 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
}

如有任何帮助,我们将不胜感激!!

java json arraylist
1个回答
0
投票

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));
}
© www.soinside.com 2019 - 2024. All rights reserved.