To n ot bardzo trudne do wykonania poprawnego foldLeft
dla Java 8 potoków:
@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];
}
albo w sposób bezpieczny typu:
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;
}
To działa prawidłowo dla sekwencyjnych i równoległych strumieni. Możesz nawet uzyskać wzmocnienie szybkości przy użyciu strumieni równoległych, jeśli twój strumień zawiera kilka nieoperacyjnych operacji pośrednich bez obciążenia procesora, takich jak map
: w tym przypadku następny element może być przetwarzany przez map
w równoległym z bieżącym elementem przetworzonym przez foldLeft
. Nie zgadzam się, że taka operacja nie jest odpowiednia dla Stream API, ponieważ można ją poprawnie wyrazić za pośrednictwem już istniejącego forEachOrdered
.
mam tę operację w moim StreamEx bibliotece, więc można go używać tak:
WebTarget target = EntryStream.of(queryParams).foldLeft(getClient().target(u),
(t, entry) -> t.queryParam(entry.getKey(), entry.getValue()))
Jestem nerwowy o tym ostatnim sumator, nawet jeśli dodano 'sekwencyjny()'. –
Ja też. Nie jestem pewien, czy to prawda. Bez żadnego odpowiednika 'foldLeft', wątpię, aby strumień API był odpowiedni w tej sytuacji. – aioobe
Myślę, że wolałbym odpowiedź, która wprost stwierdza, że strumienie naprawdę nie wspierają tego dobrze. –