Jak peek () i allMatch () współpracują ze sobą w interfejsie API Java 8 Stream


10

Znalazłem quiz na temat API Java 8 Stream metody peek, jak poniżej

Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));

Dane wyjściowe to

Fred
Jim

Nie wiem, jak działa ten strumień? Mój oczekiwany wynik powinien być

Fred
Jim
Sheila

Metoda peek () jest operacją pośrednią i przetwarza każdy element w strumieniu. Czy ktoś może mi to wyjaśnić.

Odpowiedzi:


10

Jest to optymalizacja strumienia zwana zwarciem. Zasadniczo dzieje się to, co allMatchuniemożliwia wykonanie niepotrzebnych operacji pośrednich w strumieniu, ponieważ nie ma sensu ich wykonywać, gdy znany jest wynik końcowy.

To tak, jakby to się stało:

take"Fred"
peek("Fred")
evaluate("Fred".startsWith("F"))
decide whether the result of allMatch() is known for sure: Not yet

take"Jim"
peek("Jim")
evaluate("Jim".startsWith("F"))
decide whether the result of allMatch() is known for sure: Yes

Kiedy "Jim".startsWith("F")jest oceniany, wynik allMatch(s -> s.startsWith("F"))jest znany na pewno. Nie ma znaczenia, jakie wartości przyjdą później "Jim", wiemy, że wszystkie wartości zaczynające się od „F” są fałszywe

Nie jest to specyficzne dla kombinacji peek/ allMatch, istnieje wiele operacji zwarć pośrednich i zacisków. stan java.util.streamdokumentacji pakietu :

Ponadto niektóre operacje są uważane za operacje powodujące zwarcie. Operacja pośrednia powoduje zwarcie, jeśli w przypadku nieskończonego wejścia może w rezultacie wytworzyć skończony strumień. Operacja końcowa powoduje zwarcie, jeśli w przypadku nieskończonego wejścia może zakończyć się w skończonym czasie. Posiadanie operacji zwarcia w rurociągu jest koniecznym, ale niewystarczającym warunkiem przetwarzania nieskończonego strumienia, aby zakończył się normalnie w skończonym czasie.

Rozszerz to na strumienie skończone, a operacje zwierania zapobiegają wykonywaniu niepotrzebnych kroków potoku, tak jak w twoim przykładzie.


5
Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));
  • Pierwszy raz, FredDrukowany po . Tak pasuje
  • Drugi raz, Jimdrukowany. Nie pasuje, więc allMatch kończy się, ponieważ „Wszystkie nie pasują”
  • Tak więc ostatni element nie został zużyty ze strumienia.

3

W Dokumentach do peekSay metody (nacisk kopalni)

Zwraca strumień składający się z elementów tego strumienia, dodatkowo wykonując podaną akcję na każdym elemencie, gdy elementy są konsumowane z wynikowego strumienia .

W tym przypadku peeknie widać, "Sheila"ponieważ ta wartość nie jest pobierana ze strumienia. Gdy tylko "Jim"zostanie zużyty, .allMatch(s -> s.startsWith("F"))wiadomo już , że wynik false, więc nie ma potrzeby konsumowania żadnych elementów ze strumienia.


1

Zgodnie z Java Doc Of allMatch ():

Zwraca, czy wszystkie elementy tego strumienia pasują do podanego predykatu. Może nie oceniać predykatu dla wszystkich elementów, jeśli nie jest to konieczne do ustalenia wyniku. Jeśli strumień jest pusty, zwracany jest {@code true}, a predykat nie jest oceniany.

@apiNote

Ta metoda ocenia uniwersalną kwantyfikację predykatu nad elementami strumienia (dla wszystkich x P (x)). Jeśli strumień jest pusty, mówi się, że kwantyfikacja jest pusta i zawsze ma wartość {@code true} (niezależnie od P (x)).

predykat ma zastosowanie do elementów tego strumienia @return {@code true}, jeśli wszystkie elementy strumienia pasują do podanego predykatu lub strumień jest pusty, w przeciwnym razie {@code false}

W Twoim przypadku:

1-

p(x) : s -> s.startsWith("F")

X : "Fred"

result : X P(X) = true

2-

p(x) : s -> s.startsWith("F")

X : "Jim"

result : X P(X) = false

Dalsza ocena nie będzie przeprowadzana, ponieważ XP (X) = false

boolean result = Arrays.asList("Fred", "Finda", "Fish")
            .stream()
            .peek(System.out::println)
            .allMatch(s -> s.startsWith("F"));
    System.out.println("Result "+result);

Dane wyjściowe to:

Fred
Finda
Fish
Result true

Tutaj strumień jest przetwarzany całkowicie, ponieważ xP (x) = true z każdego elementu

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.