Suppose you have a method like this that computes the maximum of a Collection
for some ToIntFunction
:
static <T> void foo1(Collection<? extends T> collection, ToIntFunction<? super T> function) {
if (collection.isEmpty())
throw new NoSuchElementException();
int max = Integer.MIN_VALUE;
T maxT = null;
for (T t : collection) {
int result = function.applyAsInt(t);
if (result >= max) {
max = result;
maxT = t;
}
}
// do something with maxT
}
With Java 8, this could be translated into
static <T> void foo2(Collection<? extends T> collection, ToIntFunction<? super T> function) {
T maxT = collection.stream()
.max(Comparator.comparingInt(function))
.get();
// do something with maxT
}
A disadvantage with the new version is that function.applyAsInt
is invoked repeatedly for the same value of T
. (Specifically if the collection has size n
, foo1
invokes applyAsInt
n
times whereas foo2
invokes it 2n - 2
times).
Disadvantages of the first approach are that the code is less clear and you can't modify it to use parallelism.
Suppose you wanted to do this using parallel streams and only invoke applyAsInt
once per element. Can this be written in a simple way?
There are several methods we can use to find the minimum or maximum values: graphing, calculus, or utilizing the standard form equation. If you are given the graph of a quadratic function or able to graph it with a calculator, then it is simple to find the maximum or minimum value.
To find the maximum and minimum value we need to apply those x values in the original function. To find the maximum value, we have to apply x = 2 in the original function. Therefore the maximum value is 7 at x = 2.
Below are the examples to illustrate the max () method The max () method of java.util.Collections class is used to return the maximum element of the given collection, according to the order induced by the specified comparator.
Excel MAX function The MAX function in Excel returns the highest value in a set of data that you specify. The syntax is as follows: MAX (number1, [number2], …)
You can use a custom collector that keeps running pair of the maximum value and the maximum element:
static <T> void foo3(Collection<? extends T> collection, ToIntFunction<? super T> function) {
class Pair {
int max = Integer.MIN_VALUE;
T maxT = null;
}
T maxT = collection.stream().collect(Collector.of(
Pair::new,
(p, t) -> {
int result = function.applyAsInt(t);
if (result >= p.max) {
p.max = result;
p.maxT = t;
}
},
(p1, p2) -> p2.max > p1.max ? p2 : p1,
p -> p.maxT
));
// do something with maxT
}
One advantage is that this creates a single Pair
intermediate object that is used through-out the collecting process. Each time an element is accepted, this holder is updated with the new maximum. The finisher operation just returns the maximum element and disgards the maximum value.
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