将一个复合对象列表进行分组

4
我有一个ArrayList(Result),其中Result对象都持有对Event对象的引用。ArrayList中可能有50个Result对象,但只有5个不同的Event对象。是否有一种方法可以遍历ArrayList并将具有相同Event.getName()引用的Results分组在一起?
我想要分别在事件“高跳”中运行方法,然后仅在事件“跳远”等中运行方法。 我事先不知道结果列表中包含哪些事件,因为它们是从用户输入创建的。
我知道如何按事件名称对ArrayList进行排序,但我希望将列表按事件拆分并将它们存储在其他临时列表中(?)
来自Result类:
public Result(double result, int attemptNumber, Participant participant, Event event) {
    this.result = result;
    this.attemptNumber = attemptNumber;
    this.participant = participant;
    this.event = event;
}

来自事件类:

public Event (String eventName, int attemptsAllowed) {
    this.eventName = eventName;
    this.attemptsAllowed = attemptsAllowed;
}

public String getEventName() {
    return eventName;
}

结果对象以未排序形式存储在名为allResults的ArrayList中。以下是第三个类中的一个方法,该方法基于输入的事件名称对所有结果进行排序和修剪,并仅保留每个参与者的最高结果(称为resultByEvent):

public ArrayList<Result> resultsByEvent(String eventName) {
    resultsByEvent.addAll(allResults);

    for(int i = 0; i < resultsByEvent.size(); i++) {
        Event event = resultsByEvent.get(i).getEvent();

        if(!event.getEventName().equals(eventName)) {
            resultsByEvent.remove(i);
        }
    }

    Collections.sort(resultsByEvent, new EventLeaderboard());

    for(int n = 0; n < resultsByEvent.size(); n++) {
        for(int j = n + 1; j < resultsByEvent.size(); j++) {
            Participant participant1 = resultsByEvent.get(n).getParticipant();
            Participant participant2 = resultsByEvent.get(j).getParticipant();

            if(participant1.getParticipantId() == participant2.getParticipantId()) {
                resultsByEvent.remove(j);
                j = j - 1;
            }
        }
    }
    return resultsByEvent;
}

以上是我想在原始结果列表中运行所有事件的内容。

3
你能否发布ResultEvent的代码? - bradimus
2
请分享一些你曾经编写过的代码。 - Naman
1
你正在使用 java-8 吗? - Chetan Kinger
1
如果我理解正确的话,您想按名称对所有事件进行分组? - Chetan Kinger
1
@AgnesAronsson 请看我的回答。 - Chetan Kinger
显示剩余2条评论
3个回答

4

您可以使用 Stream API 来实现:

按名称分组事件

Map<String, List<Event>> eventsGroupedByName = allResults.stream().collect(
                Collectors.groupingBy(e -> e.getEvent().getName()));

按事件名称分组结果

Map<String, List<Result>> resultsGroupedByEventName = allResults.stream().collect(
                Collectors.groupingBy(r -> r.getEvent().getName()));

这看起来更简洁,我会立即尝试。谢谢! - AgnesAronsson
@AgnesAronsson,你在问题上的评论说“是的,确切地说,按相同的 getEventName() 分组事件”,但看起来你想要按事件名称分组结果。我已经提供了Java-8中的两种解决方案。 - Chetan Kinger

3
您可以创建一个“事件名称”/“相应结果列表”的Map,然后当您正在查找与某个名称匹配的结果时,只需调用 List<Result> matchingResults = eventsResults.get(<some event name>)

在以下示例中,results 是您的List<Result>

        Map<String,List<Result>> eventsResults = new HashMap<String,List<Result>>();

        for(Result result : results){

            String eventName = result.getEvent().getEventName();
            // search the map for this event name
            List<Result> storedResultsList = eventsResults.get(eventName);

            if(storedResultsList == null){
                // no entry for this name yet, let's create one
                List<Result> newEventResultsList = new ArrayList<Result>();
                newEventResultsList.add(result);

                eventsResults.put(eventName, newEventResultsList);


            }
            else{
                // entry found, let's add this result to the list
                storedResultsList.add(result);
            }
        }

1
谢谢!这个可用了,正是我所需要的 :) - AgnesAronsson
1
@AgnesAronsson 你说你正在使用 java-8,我强烈建议使用新的 Stream API 来进行这种转换。请查看我的答案。 - Chetan Kinger
1
@Berger 也许你应该使用 Map::computeIfAbsent,像这样 eventsResults.computeIfAbsent(eventName, k -> new ArrayList<>()).add(result); - Flown

0
你可以创建一个列表的映射。键 = 引用,数据 = 该类型引用的列表。

我认为你指的是Map而不是Set。即使如此,为了使这个答案有用,请提供一些示例代码。 - bradimus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接