It's n ot molto difficile da attuare una corretta foldLeft
per Java 8 flussi:
@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];
}
O in maniera type-safe:
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;
}
Ciò funziona correttamente per i flussi sequenziali e paralleli. È anche possibile ottenere un guadagno di velocità utilizzando flussi paralleli se lo stream ha alcune operazioni intermedie stateless che consumano CPU come map
: in questo caso l'elemento successivo può essere elaborato da map
nel parallelo con l'elemento corrente elaborato da foldLeft
. Non sono d'accordo che tale operazione non è adatta per Stream API, perché può essere correttamente espressa tramite già esistente forEachOrdered
.
Ho questa operazione nella mia biblioteca StreamEx, in modo da poter usare in questo modo:
WebTarget target = EntryStream.of(queryParams).foldLeft(getClient().target(u),
(t, entry) -> t.queryParam(entry.getKey(), entry.getValue()))
fonte
2015-06-09 18:06:41
Sono nervoso per quell'ultimo combinatore, anche se si è aggiunto 'sequenziale()'. –
Anch'io. Non sono sicuro sia corretto Senza alcun equivalente a 'foldLeft', dubito che l'API del flusso sia adatta in questa situazione. – aioobe
Penso che preferirei una risposta che affermasse apertamente che i flussi non supportano veramente questo bene. –