Search code examples
javajava-8

How to group and sort on multiple fields?


I have a stream of objects that is grouped by two fields. I would like to sort results on the two fields (first by field1, then by field2) :

for(var group : data
   .collect(Collectors.groupingBy(x ->
        new AbstractMap.SimpleEntry(x.field1, x.field2)))
   .entrySet()
   .stream()
   .sorted(...) //not sure what to put here
   .toList()) {
}   

What I tried so far (it does not compile) :

.sorted(Comparator
   .comparing(x -> x.getKey().getKey())
   .thenComparing(x -> x.getKey().getValue()))

And :

.sorted(Map.Entry.comparingByKey(Map.EntrycomparingByKey()
                    .thenComparing(Map.Entry.comparingByValue())))

Solution

  • I have been able to achieve what I wanted this way :

    data
      .collect(Collectors.groupingBy(x -> 
                    new AbstractMap.SimpleEntry<>(x.field1, x.field2))) 
      .entrySet()
      .stream()
      .sorted(Map.Entry.comparingByKey(Map.Entry.<String,String>comparingByKey()
                                       .thenComparing(Map.Entry.comparingByValue())))
    

    The trick is to use SimpleEntry<> instead of SimpleEntry (so it stay strongly typed) and to specify the types of the fields that need to be sorted : Map.Entry.<String, String> instead of Map.Entry. I am not sure why Java is able to infer the types for the first Map.Entry.comparingByKey() call (just after the sorted() call) and not the second one.

    For complex cases, the solution suggested by mattdf is better.