Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning List of values with max property using Comparator

What is the best way to get List<MyCustomObject> from List<MyCustomObject> that have maximum value of some property?

I can write my own Comparator:

Comparator<MyCustomObject> cmp = Comparator.comparing(MyCustomObject::getIntField);

Then use it in a stream:

Optional<MyCustomObject> max = list.stream().max(cmp);

But I'm getting only one element. Is there a simple way to return all MyCustomObject that have maximum IntField and not just the first one?

like image 772
ohwelppp Avatar asked Jan 02 '23 05:01

ohwelppp


1 Answers

You only know the maximum value of the relevant property after you iterate over all the elements of the List, so one way of find the elements having the max value is to group the elements by that property into a sorted Map and get the last value:

List<MyCustomObject> max = list.stream()
                               .collect(Collectors.groupingBy (MyCustomObject::getIntField,
                                                               TreeMap::new,
                                                               Collectors.toList ()))
                               .lastEntry ()
                               .getValue ();

However, this performs more work then you actually need, and costs O(NlogN) due to the sorting. If you don't mind splitting the problem into two steps (first finding the maximum value and then collecting the elements having a property with that value), you'll have better running time (O(N)).

Since I don't have your custom object, I couldn't test the above code, but I tested similar code that takes a Stream of Strings and returns all the Strings having the max length:

List<String> max = Stream.of ("ddd","aa","EEEE","a","BB","CCC1")
                         .collect(Collectors.groupingBy (String::length,
                                                         TreeMap::new,
                                                         Collectors.toList ()))
                         .lastEntry ()
                         .getValue ();
System.out.println (max);

This returns:

[EEEE, CCC1]
like image 125
Eran Avatar answered Jan 12 '23 00:01

Eran