Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group a list of composite objects

I have an ArrayList(Result) where the Result objects all holds a reference to an Event object. There are maybe 50 Result objects in the ArrayList but only 5 different Event objects. Is there a way to loop through the ArrayList and group together Results that have identical Event.getName() references?

I want to separately run a method on results in the event 'high jump', then only on results in the event 'long jump', etc. I will not know beforehand what events my result list holds as they are created from user input.

I know how to sort the ArrayList on event name, but I want to rather split the list by event and store them in other temporary lists (?)

from Result class:

public Result(double result, int attemptNumber, Participant participant, Event event) {
    this.result = result;
    this.attemptNumber = attemptNumber;
    this.participant = participant;
    this.event = event;
}

from Event class:

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

public String getEventName() {
    return eventName;
}

Result objects are stored unsorted in an ArrayList called allResults, here is a method in a third class that sorts and trims a copy of allResults (called resultByEvent) based on input eventName and keeps only the highest result per participant:

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;
}

The above is what I want to run on all my events in the original result list.

like image 314
AgnesAronsson Avatar asked Mar 11 '23 01:03

AgnesAronsson


1 Answers

You can do this using the Stream API :

Group events by name

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

Group results by event name

Map<String, List<Result>> resultsGroupedByEventName = allResults.stream().collect(
                Collectors.groupingBy(r -> r.getEvent().getName()));
like image 192
Chetan Kinger Avatar answered Mar 30 '23 10:03

Chetan Kinger