Это n Ot очень трудно осуществить правильный foldLeft
для Java 8 потоков:
@SuppressWarnings("unchecked")
public static <T, U> U foldLeft(Stream<T> stream,
U identity, BiFunction<U, ? super T, U> accumulator) {
Object[] result = new Object[] { identity };
stream.forEachOrdered(t -> result[0] = accumulator.apply((U) result[0], t));
return (U) result[0];
}
Или в типобезопасного образом:
public static <T, U> U foldLeft(Stream<T> stream,
U identity, BiFunction<U, ? super T, U> accumulator) {
class Box {
U value;
Box(U value) { this.value = value; }
}
Box result = new Box(identity);
stream.forEachOrdered(t -> result.value = accumulator.apply(result.value, t));
return result.value;
}
Это правильно работает для последовательных и параллельных потоков. У вас может даже быть коэффициент усиления по скорости с использованием параллельных потоков, если в вашем потоке есть промежуточные операции без учета состояния, такие как map
: в этом случае следующий элемент может обрабатываться map
параллельно с текущим элементом, обработанным foldLeft
. Я не согласен с тем, что такая операция не подходит для Stream API, потому что она может быть правильно выражена через уже существующий forEachOrdered
.
я эту операцию в моей StreamEx библиотеке, так что вы можете использовать его как это:
WebTarget target = EntryStream.of(queryParams).foldLeft(getClient().target(u),
(t, entry) -> t.queryParam(entry.getKey(), entry.getValue()))
Я нервничаю о том, что последний объединителя, даже если вы добавили 'последовательный()'. –
Я тоже. Я не уверен, что это правильно. Без какого-либо эквивалента 'foldLeft', я сомневаюсь, что API потока подходит в этой ситуации. – aioobe
Я думаю, что предпочел бы ответ, который прямо заявил, что потоки на самом деле не поддерживают это. –