Eksploatacja redukcji (zwany również krotnie) wykonuje sekwencję elementów wejściowych i łączy je w pojedynczy wynik zbiorczej przez wielokrotne zastosowanie łączący operacji takie jak znajdowanie sumy lub maksimum zbioru liczb lub gromadzenie elementów na liście. Klasy strumieni mają wiele form ogólnych operacji redukcji, zwanych zmniejszeniem() i zbieraniem(), jak również wieloma specjalistycznymi formami redukcji, takimi jak sum(), max() lub count().
Oczywiście, takie działania mogą być łatwo realizowane jako prostych pętlach sekwencyjnych, na przykład:
int sum = 0;
for (int x : numbers) {
sum += x;
}
Jednakże istnieją powody, aby wolą zmniejszyć działanie na mutative akumulacji takie jak powyżej. Redukcja nie tylko jest "bardziej abstrakcyjna" - działa raczej na strumieniu jako całości niż na poszczególnych elementach - ale prawidłowo wykonana operacja zmniejszania jest z natury rzeczy możliwa do zrównoleglenia, o ile funkcja (y) używana do przetwarzania elementów są asocjacyjne i bezpaństwowców. Na przykład, biorąc pod uwagę strumień liczb, dla których chcemy znaleźć sumę, możemy napisać:
int sum = numbers.stream().reduce(0, (x,y) -> x+y);
lub:
int sum = numbers.stream().reduce(0, Integer::sum);
Te operacje redukcji może bezpiecznie działać równolegle z prawie bez zmian:
int sum = numbers.parallelStream().reduce(0, Integer::sum);
_ "ale składnia nie brzmi dobrze" _ Co sprawia, że tak myślisz? To jest zwykły idiom. Może chcesz użyć 'mapToLong', aby uniknąć przepełnień, w zależności od wartości, jakie może posiadać twoja mapa. –
@JBNizet Uważam, że 'i -> i' jest bardzo jasne, osobiście. Cóż, tak, musisz wiedzieć, że wartość zostanie automatycznie rozpakowana, ale to prawda, ponieważ Java 5 ... –
@AlexisC. Jest to zrozumiałe, ponieważ jest przekazywane do mapToInt(), a ponieważ jestem doświadczonym programistą. Ale ja -> i, bez kontekstu, wygląda jak noop. Integer :: intValue jest bardziej szczegółowy, ale powoduje wyraźną operację rozpakowywania. –