Search code examples
dictionaryjava-8java-streamtreemapcollectors

Stream grouping by sum of determinate objects


I have a Request class like this :

public class Request 
{
String name,destName;
int nSeats;
//Example : requestOne,Paris,3
...
}

I want to group the request in a Map |Integer,List of String| where the keys are the sum of the request with the same destName and the values are the destinations' names.

Here is my code:

public TreeMap<Integer, List<String>> destinationsPerNSeats() {
return requests.
stream().
collect(Collectors.groupingBy(Request::getnSeats, TreeMap::new, 
Collectors.mapping(Request::getDestName, Collectors.toList()))).
}

Input :

TreeMap<Integer, List<String>> map = mgr.destinationsPerNSeats();
print(map);

Output : {4=[Paris], 3=[London, Berlin, Berlin], 2=[Paris]}

Output expected : {6=[Berlin, Paris], 3=[London]}

How can I solve this? Thanks!


Solution

  • I think you need two Stream pipelines. The first will group the destinations and sum the total number of seat for each destination name, and the second will group the destination names by the number of seats:

    public TreeMap<Integer, List<String>> destinationsPerNSeats() {
        return
            requests.stream()
                    .collect(Collectors.groupingBy(Request::getDestName, 
                                                   Collectors.summingInt(Request::getnSeats)))
                    .entrySet()
                    .stream()
                    .collect(Collectors.groupingBy(Map.Entry::getValue,
                                                   TreeMap::new,
                                                   Collectors.mapping(Map.Entry::getKey,Collectors.toList())));
    }
    

    Testing your code with the following input:

    List<Request> requests = new ArrayList<> ();
    requests.add (new Request("John","Paris",4));
    requests.add (new Request("Ben","London",3));
    requests.add (new Request("Dan","Berlin",3));
    requests.add (new Request("Sara","Berlin",3));
    requests.add (new Request("Jenn","Paris",2));
    

    produces the Map:

    {3=[London], 6=[Berlin, Paris]}