-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmin_max.java
51 lines (40 loc) · 3.04 KB
/
min_max.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Решение задачи Минимум и максимум.
У стрима есть методы min() и max(), но воспользоваться ими «в лоб» нельзя, т.к. оба являются терминальными
операциями. Использовав одну из них, вторую уже вызвать нельзя — стрим бросит IllegalStateException.
Некоторые обходили это ограничение,
собирая элементы стрима в коллекцию, из которой можно было получить новый стрим столько раз, сколько нужно.
Это решение проходит тесты, но его большой недостаток — необходимость хранить в памяти все элементы стрима,
которых может быть очень много. Мы заранее не знаем, сколько их будет.
Оптимальным решением является нахождение минимума и максимума за один проход по стриму без использования
промежуточного хранилища элементов. Сделать это несложно:
public static <T> void findMinMax(
Stream<? extends T> stream,
Comparator<? super T> order,
BiConsumer<? super T, ? super T> minMaxConsumer) {
MinMaxFinder<T> minMaxFinder = new MinMaxFinder<>(order);
stream.forEach(minMaxFinder);
minMaxConsumer.accept(minMaxFinder.min, minMaxFinder.max);
}
private static class MinMaxFinder<T> implements Consumer<T> {
private final Comparator<? super T> order;
T min;
T max;
private MinMaxFinder(Comparator<? super T> order) {
this.order = order;
}
@Override
public void accept(T t) {
if (min == null || order.compare(t, min) < 0) {
min = t;
}
if (max == null || order.compare(max, t) < 0) {
max = t;
}
}
}
Обратите внимание, что решение не использует приведение типа к (T). Благодаря этому отсутствуют
предупреждения компилятора о небезопасном приведении типов. В других решениях, где Consumer
реализован как лямбда-выражение или как анонимный класс, избежать предупреждений было бы гораздо сложнее.
P.S. В лекциях были рассмотрены только последовательные стримы, однако в Java бывают еще
и параллельные стримы, обрабатывающие свои элементы одновременно в нескольких потоках.
Это решение для параллельных стримов не подходит. Но это уже совсем другая история...