I have a stream of objects and I would like to find the one with a maximal value of some attribute that's expensive to calculate.
As a specific simple example, say that we have a list of strings and we want to find the coolest one, given a coolnessIndex
function.
The following should work:
String coolestString = stringList .stream() .max((s1, s2) -> Integer.compare(coolnessIndex(s1), coolnessIndex(s2))) .orElse(null);
Now, there are two problems with this. First, assuming the coolnessIndex
is expensive to calculate, this probably won't be very efficient. I suppose the max
method will need to use the comparator repeatedly, which in turn will call the coolnessIndex
repeatedly and at the end it will be called more than once for each string.
Second, having to provide the comparator leads to some redundancy in the code. I would much prefer syntax like this:
String coolestString = stringList .stream() .maxByAttribute(s -> coolnessIndex(s)) .orElse(null);
However, I haven't been able to find a matching method in the Stream
API. This surprises me, since finding min/max by an attribute seems like a common pattern. I wonder if there's a better way than using the comparator (other than a for loop).
We can find Maximum and Minimum using simply iterate the HashSet and maintain the min and max variable and update it accordingly while traversing through each element and comparing it with the min and max values.
With the introduction of Stream with Java 8, we can convert the array into the corresponding type stream using the Arrays. stream() method. Then we can call the max() and min() method, which returns the maximum and minimum element of this stream as OptionalInt .
Stream<String> stringStream = stringList.stream(); String coolest = stringStream.reduce((a,b)-> coolnessIndex(a) > coolnessIndex(b) ? a:b; ).get()
Here's a variant using an Object[]
as a tuple, not the prettiest code but concise
String coolestString = stringList .stream() .map(s -> new Object[] {s, coolnessIndex(s)}) .max(Comparator.comparingInt(a -> (int)a[1])) .map(a -> (String)a[0]) .orElse(null);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With