Peek () ve allMatch (), Java 8 Stream API'sında birlikte nasıl çalışır?


10

Aşağıdaki gibi peek yöntemi Java 8 Stream API hakkında bir sınav buldum

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

Çıktı

Fred
Jim

Bu akışın nasıl çalıştığı konusunda kafam karıştı Beklediğim sonuç

Fred
Jim
Sheila

Peek () yöntemi bir ara işlemdir ve Stream'deki her öğeyi işler. Birisi bana bunu açıklayabilir mi?

Yanıtlar:


10

Kısa devre olarak bilinen bir akış optimizasyonu. Esasen, akışta allMatchgereksiz ara işlemlerin yürütülmesini önleyen şeydir , çünkü nihai sonuç bilindiğinde bunları gerçekleştirmenin bir anlamı yoktur.

Sanki bu oldu:

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

Zaman "Jim".startsWith("F")değerlendirilmiştir, sonucu allMatch(s -> s.startsWith("F"))kesin olarak bilinmektedir. Ne de olsa değerler boru hattında gelip ne olduğu önemli değildir "Jim"bunu biliyoruz, tüm değerler "F" ile başlayan yanlış

Bu peek/ allMatchkombinasyonuna özgü değildir , çoklu ara ve terminal kısa devre işlemleri vardır. java.util.streampaketin doküman durumu:

Ayrıca, bazı operasyonlar kısa devre operasyonları olarak kabul edilir. Sonsuz girdi ile sunulduğunda sonuç olarak sınırlı bir akım üretebiliyorsa, bir ara işlem kısa devre yapar. Bir terminal işlemi sonsuz girişle sunulduğunda sonlu sürede sonlanabilirse kısa devre yapar. Boru hattında kısa devre operasyonuna sahip olmak, sonsuz bir akımın işlenmesinin sonlu sürede normal olarak sonlanması için gerekli, ancak yeterli değildir.

Bunu sonlu akışlara genişletin ve kısa devre işlemleri, örneğinizde olduğu gibi gereksiz boru hattı adımlarının yürütülmesini engeller.


5
Arrays.asList("Fred", "Jim", "Sheila")
      .stream()
      .peek(System.out::println)
      .allMatch(s -> s.startsWith("F"));
  • İlk kez Fred, basılır. Öyle ki
  • İkinci kez Jim, basılır. "Tümü eşleşmedi" için allMatch sona erdiğinden eşleşmiyor
  • Bu nedenle, son öğe akıştan tüketilmedi.

3

Docs için peekyöntem söz hakkından (vurgu benim):

Bu akışın elemanlarından oluşan bir akış döndürür, ayrıca sonuç olarak elde edilen akıştan elemanlar tüketilirken her bir eleman üzerinde sağlanan eylemi gerçekleştirir .

Yani bu durumda, peekgörmez "Sheila"bu değer akışından tüketilen çünkü. Yakında Olarak "Jim"tüketildiği, sonucu .allMatch(s -> s.startsWith("F"))önceden bilinen olması false, bu nedenle akışından daha fazla unsurları tüketmeye gerek yoktur.


1

Java Doc Of allMatch () uyarınca:

Bu akışın tüm öğelerinin sağlanan yüklemle eşleşip eşleşmediğini döndürür. Sonucu belirlemek için gerekli değilse, tüm elementler üzerindeki yüklemi değerlendiremeyebilir. Akış boşsa, {@code true} döndürülür ve yüklem değerlendirilmez.

@apiNote

Bu yöntem , akımın elemanları üzerindeki yüklemin evrensel nicelleştirilmesini değerlendirir (tüm x P (x) için). Akış boşsa, nicelemenin boş bir şekilde karşılandığı ve her zaman {@code true} (P (x) ne olursa olsun) olduğu söylenir.

Akışın tüm öğeleri sağlanan yüklemle eşleşiyorsa veya akış boşsa, bu akışın @return {@code true} öğelerine uygulanacak şekilde yüklemesi, aksi halde {@code false}

Senin durumunda:

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

Daha fazla değerlendirme yapılmayacaktır, çünkü XP (X) = yanlış

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

Çıktı:

Fred
Finda
Fish
Result true

Burada akış tamamen işlendi çünkü her öğeden xP (x) = true

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.