Java 8'de Ayırıcı, Toplayıcı ve Akışı Anlama


143

StreamJava 8'deki arayüzü anlamakta zorlanıyorum , özellikle Spliteratorve Collectorarayüzleri ile ilgili olduğu yerde . Benim sorunum sadece anlayamıyorum Spliteratorve Collectorarayüzler ve sonuç olarak, Streamarayüz hala biraz karanlık.

A Spliteratorve a tam olarak nedir Collectorve bunları nasıl kullanabilirim? Eğer kendim Spliteratorveya Collector(ve muhtemelen Streambu süreçte kendiminkini) yazmaya istekliysem ne yapmam ve yapmamam gerekir?

Web'e dağılmış bazı örnekleri okudum, ancak buradaki her şey hala yeni ve değişikliklere tabi olduğundan, örnekler ve öğreticiler hala çok seyrek.

Yanıtlar:


142

Neredeyse kesinlikle kesinlikle Spliteratorbir kullanıcı olarak uğraşmak zorunda kalmamalısınız ; Sen yazı eğer sadece gerekli olmalıdır Collectiontürleri kendinizi ve ayrıca optimize niyetinde onlara işlemleri parallelized.

Değeri ne Spliteratorolursa olsun, bir koleksiyonun öğeleri üzerinde koleksiyonun bir bölümünü kolayca ayırabileceğiniz şekilde çalışmanın bir yoludur, çünkü paralelleştiriyorsunuz ve koleksiyonun bir parçası üzerinde bir iş parçacığının çalışmasını istiyorsanız, bir iplik başka bir parça üzerinde çalışmak, vb.

Aslında, tür değerlerini de asla Streambir değişkene kaydetmemelisiniz . Streamsıralama bir benzeri olan Iteratorbu size hemen hemen her zaman Javadoc örnekte olduğu gibi bir akıcı zincirinde kullanacağınız bir kerelik kullanımlık obje olması açısından,:

int sum = widgets.stream()
                  .filter(w -> w.getColor() == RED)
                  .mapToInt(w -> w.getWeight())
                  .sum();

Collectorbir harita / indirgeme "azaltma" işleminin en genelleştirilmiş, soyut olası versiyonudur; özellikle, paralelleştirme ve sonlandırma adımlarını desteklemesi gerekir. S örnekleri Collectorşunları içerir:

  • özetleme, ör. Collectors.reducing(0, (x, y) -> x + y)
  • StringBuilder ekleniyor, ör. Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString)

31
Spliterator (s) ayrıca bir Koleksiyon olmayan bir Yinelenebilir akış için bir yol sağlar
Bohemian

2
"Terimin harita / indirgeme anlamına gelmesi anlamında bir azaltma işlemi" demek istedim
Louis Wasserman

1
Collectors.ofkaldırıldı ya ben am şey eksik beta sürümünün eski bir yöntemi? Bütünlük (x,y) -> x+yiçin yazılabilir Integer::sum.
Jean-François Savard

3
Hayır, üzgünüm, bu Koleksiyoner değil, Koleksiyonerler değil.
Louis Wasserman

2
Koleksiyonerlerinizin her birinin ne yaptığını açıklarsanız, Koleksiyoncu örneğiniz daha yararlı olacaktır.
MiguelMunoz

90

Spliterator temelde "ayrılabilir Yineleyici" anlamına gelir.

Tek bir iş parçacığı tüm Spliterator'ın kendisini geçebilir / işleyebilir, ancak Spliterator aynı zamanda başka bir parçanın trySplit()(tipik olarak başka bir iş parçacığı) işlemesi için bir bölümü "ayırır" - mevcut ayırıcıyı daha az çalışma ile bırakır.

Collectorbir reduceişlevin (harita azaltma şöhretinin) belirtimini bir başlangıç ​​değeriyle ve iki sonucu birleştirmek için bir işlevi birleştirir (böylece bölünmüş çalışma akışlarından elde edilen sonuçların birleştirilmesini sağlar).

Örneğin, en temel Toplayıcı başlangıç ​​değeri 0 olur, mevcut bir sonuca bir tamsayı ekler ve iki sonucu ekleyerek 'birleştirir'. Böylece bölünmüş bir tamsayılar akışı toplanır.

Görmek:


sonucu birleştirmek için bir değer?
Jason Law

@JasonLaw - açıklandı! Önerin için teşekkürler.
Thomas W

5

Aşağıdakiler, ortak değişken değiştirilebilir görevleri gerçekleştirmek için önceden tanımlanmış toplayıcıların kullanımına ilişkin örneklerdir:

 // Accumulate names into a List
 List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());

 // Accumulate names into a TreeSet
 Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));

 // Convert elements to strings and concatenate them, separated by commas
 String joined = things.stream()
                       .map(Object::toString)
                       .collect(Collectors.joining(", "));

 // Compute sum of salaries of employee
 int total = employees.stream()
                      .collect(Collectors.summingInt(Employee::getSalary)));

 // Group employees by department
 Map<Department, List<Employee>> byDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment));

 // Compute sum of salaries by department
 Map<Department, Integer> totalByDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                                               Collectors.summingInt(Employee::getSalary)));

 // Partition students into passing and failing
 Map<Boolean, List<Student>> passingFailing =
     students.stream()
             .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));

2
Bu, Op sorusuna cevap vermez, ayrıca yayınınızın açıklaması veya açıklaması yoktur.
Sid

4

Arayüz Spliterator- Akışların temel özelliğidir .

stream()Ve parallelStream()varsayılan yöntemler sunulmuştur Collectionarayüzüne. Bu yöntemler Spliterator'ı aşağıdaki çağrı ile kullanır spliterator():

...

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

...

Spliterator, akışı daha küçük parçalara ayıran dahili bir yineleyicidir. Bu daha küçük parçalar paralel olarak işlenebilir.

Diğer yöntemlerin yanı sıra, Bölücüyü anlamak için en önemli iki şey vardır:

  • boolean tryAdvance(Consumer<? super T> action)Iteratorİşlemin aksine, bir sonraki öğeyle işlemi gerçekleştirmeye çalışır. İşlem başarıyla yürütülürse yöntem geri döner true. Aksi takdirde, döndürür false- bu, öğenin veya akışın sonunun olmadığı anlamına gelir.

  • Spliterator<T> trySplit() Bu yöntem, bir veri kümesinin bir veya başka ölçütlere (dosya boyutu, satır sayısı, vb.) Göre çok daha küçük kümelere bölünmesine izin verir.


Operationİşlem başarılı bir şekilde yürütülürse ... probably Muhtemelen bunu yeniden yazmalısınız. tryAdvance javadoc daha açıktır: remainingBir kalan öğe varsa, verilen eylemi gerçekleştirir ve doğru döndürür; else false döndürür.´
Piro diyor
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.