2017-11-12 71 views
6

Dlaczego oba c1 i c2 nie są traktowane jako dwa ciągi, ale zamiast jednego: String i jednego Integer?Funkcja odszyfrowywania funkcji zmniejszania strumienia

Arrays.asList("duck","chicken","flamingo","pelican") 
      .stream() 
      .reduce(0, 
        (c1, c2) -> c1.length() + c2.length(), 
        (s1, s2) -> s1 + s2); 
+1

Czytałaś [documenation] (https://docs.oracle.com/javase/8/docs/api/?java/util/stream/Stream.html)? Co sprawia, że ​​myślisz, że byliby tego samego typu? – shmosel

Odpowiedz

4

Istnieją trzy warianty z metody reduce, które różnią się ich typami podpisów i zwracanych. jeśli spojrzeć na przeciążenia dla reduce który ma ten podpis:

reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) 

Jak widać z podpisem Ta metoda przeciążenie reduce ma 3 parametry tożsamości, akumulatorowe i sumator. Wartość tożsamości jest wartością początkową przekazaną do reduce, tj. (0), następnie mamy akumulator, który zasadniczo zawiera dodatkowy element do wyniku, a na końcu, kombinator, którego zadaniem jest połączenie dwóch podanych wartości.

więc zapytać:

Dlaczego zarówno C1 i C2 nie są postrzegane jako dwa ciągi lecz jeden String i jeden Integer?

Pierwszym argumentem BiFunction jest U który w danym przypadku jest Integer tak więc, w rodzaju stosowanych do wartości tożsamości musi być tego samego typu pierwszego argumentu, a także zwracany typ akumulatora funkcja (BiFunction).

Poza tym, trzeba to zmienić:

(c1, c2) -> c1.length() + c2.length() 

do tego:

(c1, c2) -> c1 + c2.length() 

ważne jest, aby pamiętać, że sumator funkcja(s1, s2) -> s1 + s2 nie zostanie wywołana w ogóle. Powodem tego jest to, że to specyficzne przeciążenie zostało zaprojektowane do użycia z parallelStream, więc aby zestaw mógł działać, strumień musi być równoległy w stosunku do. W przeciwnym razie zostanie wywołana tylko funkcja akumulatora.

jako strony, twój pełny kod można uprościć do:

int result = Stream.of("duck","chicken","flamingo","pelican") 
        .reduce(0, 
        (c1, c2) -> c1 + c2.length(), 
        (s1, s2) -> s1 + s2); 

lub nawet lepiej, jeśli chcesz uniknąć napowietrznej boks/unboxing z reduce:

int result = Stream.of("duck", "chicken", "flamingo", "pelican") 
        .mapToInt(String::length) 
        .sum(); 
1

wierzę, że staramy się wykonać następujące czynności:

Arrays.asList("duck", "chicken", "flamingo", "pelican") 
    .stream() 
    .map(c -> c.length()) 
    .reduce((c1, c2) -> c1 + c2); 

Najpierw map każdy ciąg do jego długości, w zasadzie robi następującą transformację:

("duck", "chicken", "flamingo", "pelican") -> (4, 7, 8, 7) 

Następnie zmniejszyć które wynikają z dodania wartości.

+1

Tak, dokładnie. Dlaczego nie można tego zrobić tak, jak napisałem powyżej? – JonJavaK

+1

Proszę zobaczyć odpowiedź Aominè. Używasz przeciążonej wersji redukcji, która prawdopodobnie nie robi tego, co chcesz. – nicovank