[英]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.