Given a list of items with properties, I am trying to get the last item to appear with a maximum value of said property.
For example, for the following list of objects:
t i A: 3 D: 7 * F: 4 C: 5 X: 7 * M: 6 I can get one of the Things with the highest i:
Thing t = items.stream() .max(Comparator.comparingLong(Thing::getI)) .orElse(null); However, this will get me Thing t = D. Is there a clean and elegant way of getting the last item, i.e. X in this case?
One possible solution is using the reduce function. However, the property is calculated on the fly and it would look more like:
Thing t = items.stream() .reduce((left, right) -> { long leftValue = valueFunction.apply(left); long rightValue = valueFunction.apply(right); return leftValue > rightValue ? left : right; }) .orElse(null); The valueFunction now needs to be called nearly twice as often.
Other obvious roundabout solutions are:
- Store the object in a Tuple with its index
- Store the object in a Tuple with its computed value
- Reverse the list beforehand
- Don't use Streams
max, thegetImethod will be called again and again for every comparison, not just once per element. In your example, it's called 11 times, including 6 times for D. How about you just cache the calculated value directly in the Thing instance?reducebased solution will work in parallel, as long as the reduction function fulfills the associativity constraint. Which is the case here.