簡體   English   中英

JAVA:如何基於屬性值合並arrayList中的對象?

[英]JAVA: How do I merge objects from an arrayList based on a property value?

我正在使用Spring Boot,Java和MySQL構建(或學習如何)運動REST API。 我正在構建一個方法,該方法當前從匹配項集合中獲取每個匹配項,並為完整的匹配項列表返回TeamStandingsArrayList

方法如下:

public List<TeamStanding> createStandingsTable(Match[] matches){
        List<TeamStanding> teamStandings = new ArrayList<TeamStanding>();
        for(int i = 0;i < matches.length; i++) {
            TeamStanding firstTeam = new TeamStanding();
            TeamStanding secondTeam = new TeamStanding();

            //set team ids
            firstTeam.setIdTeam(matches[i].getWcmHome());
            secondTeam.setIdTeam(matches[i].getWcmAway());


            //first team stats
            firstTeam.setTeamPlayed((long) 1);
            firstTeam.setTeamGoalsFavor(matches[i].getWcmHomeGoals());
            firstTeam.setTeamGoalsAgainst(matches[i].getWcmAwayGoals());
            firstTeam.setTeamGoalDif(firstTeam.getTeamGoalsFavor() - firstTeam.getTeamGoalsAgainst());

            //second team stats
            secondTeam.setTeamPlayed((long) 1);
            secondTeam.setTeamGoalsFavor(matches[i].getWcmAwayGoals());
            secondTeam.setTeamGoalsAgainst(matches[i].getWcmHomeGoals());
            secondTeam.setTeamGoalDif(secondTeam.getTeamGoalsFavor() - secondTeam.getTeamGoalsAgainst());

            //combined team stats

            if(firstTeam.getTeamGoalsFavor() > secondTeam.getTeamGoalsFavor()) {
                firstTeam.setTeamWins((long) 1);
                firstTeam.setTeamLoses((long) 0);
                firstTeam.setTeamDraws((long) 0);
                firstTeam.setTeamPoints((long) 3);
                secondTeam.setTeamWins((long) 0);
                secondTeam.setTeamLoses((long) 1);
                secondTeam.setTeamDraws((long) 0);
                secondTeam.setTeamPoints((long) 0);
            } else if (firstTeam.getTeamGoalsFavor() == secondTeam.getTeamGoalsFavor()) {
                firstTeam.setTeamWins((long) 0);
                firstTeam.setTeamLoses((long) 0);
                firstTeam.setTeamDraws((long) 1);
                firstTeam.setTeamPoints((long) 1);
                secondTeam.setTeamWins((long) 0);
                secondTeam.setTeamLoses((long) 0);
                secondTeam.setTeamDraws((long) 1);
                secondTeam.setTeamPoints((long) 1);
            } else {
                firstTeam.setTeamWins((long) 0);
                firstTeam.setTeamLoses((long) 1);
                firstTeam.setTeamDraws((long) 0);
                firstTeam.setTeamPoints((long) 0);
                secondTeam.setTeamWins((long) 1);
                secondTeam.setTeamLoses((long) 0);
                secondTeam.setTeamDraws((long) 0);
                secondTeam.setTeamPoints((long) 3);
            }
            teamStandings.add(firstTeam);
            teamStandings.add(secondTeam);
        }
        return teamStandings;
    }

結果是這樣的:

[
    {
        "idTeam": 7,
        "teamPoints": 3,
        "teamPlayed": 1,
        "teamWins": 1,
        "teamDraws": 0,
        "teamLoses": 0,
        "teamGoalsFavor": 4,
        "teamGoalsAgainst": 1,
        "teamGoalDif": 3
    },
    {
        "idTeam": 13,
        "teamPoints": 0,
        "teamPlayed": 1,
        "teamWins": 0,
        "teamDraws": 0,
        "teamLoses": 1,
        "teamGoalsFavor": 1,
        "teamGoalsAgainst": 4,
        "teamGoalDif": -3
    },
    {
        "idTeam": 4,
        "teamPoints": 3,
        "teamPlayed": 1,
        "teamWins": 1,
        "teamDraws": 0,
        "teamLoses": 0,
        "teamGoalsFavor": 1,
        "teamGoalsAgainst": 0,
        "teamGoalDif": 1
    },
    {
        "idTeam": 7,
        "teamPoints": 0,
        "teamPlayed": 1,
        "teamWins": 0,
        "teamDraws": 0,
        "teamLoses": 1,
        "teamGoalsFavor": 0,
        "teamGoalsAgainst": 1,
        "teamGoalDif": -1
    }
]

我的問題是如何基於idTeam合並這些對象? 我試圖實現的結果是,在idTeam保持不變的情況下,將所有其他屬性加起來。 在給定的示例中,預期的是:

[
        {
            "idTeam": 7,
            "teamPoints": 3,
            "teamPlayed": 2,
            "teamWins": 1,
            "teamDraws": 0,
            "teamLoses": 1,
            "teamGoalsFavor": 4,
            "teamGoalsAgainst": 2,
            "teamGoalDif": 2
        },
        {
            "idTeam": 13,
            "teamPoints": 0,
            "teamPlayed": 1,
            "teamWins": 0,
            "teamDraws": 0,
            "teamLoses": 1,
            "teamGoalsFavor": 1,
            "teamGoalsAgainst": 4,
            "teamGoalDif": -3
        },
        {
            "idTeam": 4,
            "teamPoints": 3,
            "teamPlayed": 1,
            "teamWins": 1,
            "teamDraws": 0,
            "teamLoses": 0,
            "teamGoalsFavor": 1,
            "teamGoalsAgainst": 0,
            "teamGoalDif": 1
        }
    ]

同樣,只是一個細節,我首先構建了TeamStandingsArrayList ,現在嘗試合並它們,但是也許我應該將它們堆疊成Matches數組中的循環,但在上面的相同方法中,但我不確定。

遍歷TeamStanding的列表,注意團隊ID並執行添加。 您可能希望使用地圖將一對團隊ID保存為鍵,將團隊本身保存為值,以便於操作。 這是片段(我尚未測試過,因此您可能需要對其進行一些修改)。

List<TeamStanding> list = createStandingsTable(matches);
Map<Integer, TeamStanding> map = new HashMap<>();

for (TeamStanding team: list) {
    int id = team.getIdTeam();
    if (map.containsKey(id)) {
        TeamStanding other = map.get(id);
        other.setTeamPoints(team.getTeamPoints());
        other.setTeamPlayed(team.getTeamPlayed());
        // and so on...
    } else {
        map.put(id, team);
    }
}

List<TeamStanding> merged = new ArrayList<>(map.values());

如果要直接從Match[]創建合並的List<TeamStanding> ,則必須使用相同的想法,但是,將兩個迭代合並在一起可能會有些復雜。 然后,我建議您堅持使用這兩個單獨的迭代。 簡短性,可讀性和可維護性優於性能-此外,此處的性能並不是真正的問題。

您可以使用HashMap。 使用“ idTeam”作為鍵,使用對象TeamStanding作為值。 現在,您可以在結果列表上進行迭代,如果在地圖上找到對象,則只需更新其字段即可;如果找不到,則插入對象。 迭代完成后,您可以調用map.values(),它將為您提供對象的集合(TeamStanding),然后您可以使用此集合創建一個新的ArrayList。

該代碼將如下所示:

public List<TeamStanding> mergeTeamStandingList(List<TeamStanding> teamStandingList) {
    final Map<Integer, TeamStanding> idTeamVsTeamStandingMap = new HashMap<Integer, TeamStanding>();
    teamStandingList.forEach(teamStanding -> {
        if(idTeamVsTeamStandingMap.containsKey(teamStanding.getIdTeam())) {
            TeamStanding teamStanding1 = idTeamVsTeamStandingMap.get(teamStanding.getIdTeam());
            teamStanding1.setTeamDraws(teamStanding1.getTeamDraws() + teamStanding.getTeamDraws());
            //so on
        } else {
            idTeamVsTeamStandingMap.put(teamStanding.getIdTeam(), teamStanding);
        }
    });

    return new ArrayList<>(idTeamVsTeamStandingMap.values());
}

在您的Teamstanding對象上創建合並方法。

public TeamStanding merge(TeamStanding other) {
     this.teamPoints += other.getTeamPoints();
     this.teamPlayed += other.getTeamPlayed();
     this.teamWins += other.getTeamWins();
     this.teamDraws += other.getTeamDraws();
     this.teamGoalsFavor += other.getTeamGoalsFavor();
     this.teamLoses += other.getTeamLoses();
     this.teamGoalDif += other.getTeamGoalDif();
     return this;
}

然后使用Streams按teamId分組,並使用merge方法減少常見項目。

Map<Integer, Optional<TeamStanding>> mapReduced = teamStandings
.stream()
.collect(groupingBy(TeamStanding::getIdTeam, Collectors.reducing(TeamStanding::merge)));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM