[英]JAVA: How do I merge objects from an arrayList based on a property value?
我正在使用Spring Boot,Java和MySQL構建(或學習如何)運動REST API。 我正在構建一個方法,該方法當前從匹配項集合中獲取每個匹配項,並為完整的匹配項列表返回TeamStandings
的ArrayList
。
方法如下:
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
}
]
同樣,只是一個細節,我首先構建了TeamStandings
的ArrayList
,現在嘗試合並它們,但是也許我應該將它們堆疊成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.