Я пытаюсь понять, есть ли способ прекратить операцию сокращения без изучения всего потока, и я не могу понять способ.
Пример использования выглядит примерно так: пусть будет длинный список Integer
, который нужно сложить в Accumulator
. Каждый элемент экзамена потенциально дорог, поэтому в Accumulator
я выполняю проверку входящего Accumulator
, чтобы увидеть, нужно ли нам даже выполнять дорогостоящую операцию - если мы этого не сделаем, я просто возвращаю аккумулятор.
Это, по-видимому, прекрасное решение для небольших (er) списков, но огромные списки несут излишние затраты на поток, которые я бы хотел избежать.
Здесь эскиз кода - предполагайте только последовательные сокращения.
class Accumulator {
private final Set<A> setA = new HashSet<>;
private final Set<B> setB = new HashSet<>;
}
class ResultSupplier implements Supplier<Result> {
private final List<Integer> ids;
@Override
public Result get() {
Accumulator acc = ids.stream().reduce(new Accumulator(), f(), (x, y) -> null);
return (acc.setA.size > 1) ? Result.invalid() : Result.valid(acc.setB);
}
private static BiFunction<Accumulator, Integer, Accumulator> f() {
return (acc, element) -> {
if (acc.setA.size() <= 1) {
// perform expensive ops and accumulate results
}
return acc;
};
}
}
В дополнение к тому, чтобы пройти весь Stream
, есть еще один факт, который мне не нравится: мне нужно дважды проверить одно и то же условие (а именно, setA
проверка размера).
Я рассмотрел операции map()
и collect()
, но они просто казались более похожими и не обнаружили, что они существенно меняют тот факт, что я просто не могу закончить операцию сбрасывания без изучения всего потока.
Кроме того, я думаю, что мнимый takeWhile(p : (A) => boolean)
корреспондент Stream API также не будет нам ничего не покупать, поскольку условие завершения зависит от аккумулятора, а не от потоков элементов как таковых.
Имейте в виду, что я относительный новичок в FP - есть ли способ сделать эту работу так, как я ожидаю? Я создал всю проблему неправильно или это ограничение по дизайну?