繁体   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