Как Tagir Valeev observed, (+1) функция объединения не является ассоциативной, поэтому reduce()
не будет работать, и невозможно создать функцию объединителя для Collector
. Вместо этого эту функцию объединения нужно применять слева направо, при этом предыдущий частичный результат будет передан в следующую операцию. Это называется операцией fold-left, и, к сожалению, Java-потоки не имеют такой операции.
(Должен ли они? Дай мне знать.)
Можно сортировать-вписать свою откидывающуюся влево операцию с forEachOrdered
во время захвата и мутирует объект для проведения частичного состояния. Во-первых, давайте извлекать функцию объединения в его собственный метод:
// extracted from Tagir Valeev's answer
void combine(List<Integer> list, int n) {
if (!list.isEmpty() && Math.abs(list.get(list.size()-1)-n) < 2)
list.set(list.size()-1, list.get(list.size()-1)+n);
else
list.add(n);
}
Затем создайте первоначальный список результатов и вызова функции объединения изнутри forEachOrdered
:
List<Integer> result = new ArrayList<>();
IntStream.of(5, 2, 2, 5, 13)
.forEachOrdered(n -> combine(result, n));
Это дает желаемый результат
[5, 9, 13]
В принципе это можно сделать на параллельном потоке, но производительность, вероятно, ухудшится до последовательной, учитывая семантику forEachOrdered
. Также обратите внимание, что операции forEachOrdered
выполняются по одному, поэтому нам не нужно беспокоиться о безопасности потоков данных, которые мы мутируем.
Вы можете выполнить оператор сканирования довольно легко с помощью [ 'Arrays.parallelPrefix (массив, Integer :: сумма)'] (http://docs.oracle.com/javase/8/docs/api/java /util/Arrays.html#parallelPrefix-int:A-java.util.function.IntBinaryOperator-). Но то, что вы хотите сделать, не похоже на оператора сканирования ... – Holger
Я уже решил его с оператором сканирования с чем-то вроде '(x, y) -> (abs (x-y <2))? x + y: y' – artkoenig
Тогда у вас есть «решение». Кроме того, в вашем описании говорится, что вы хотите иметь список результатов другого размера, чем оригинальный, и оператор сканирования не делает этого ... – Holger