5 Şubat 2018 Pazartesi

Stream collect metodu

collect metodu - Collector
İmzası şöyle.
<R, A> R collect(Collector<? super T, A, R> collector);
Örnek
Elimizde bir Collector olsun.
class PackCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {

  @Override
  public Supplier<List<List<T>>> supplier() {
    return () -> {
      ...
    };
  }

  @Override
  public BiConsumer<List<List<T>>, T> accumulator() {
    return (list, s) -> {
      ...
    };
  }

  @Override
  public BinaryOperator<List<List<T>>> combiner() {
    return (left, right) -> {
      ...
    };
  }

  @Override
  public Set<Characteristics> characteristics() {
    return EnumSet.of(Characteristics.IDENTITY_FINISH);
  }

  @Override
  public Function<List<List<T>>, List<List<T>>> finisher() {
    return Function.identity();
  }

}
Şöyle yaparız.
List<List<String>> result = items.stream().parallel().collect(new PackCollector<>());
System.out.println(result);
collect metodu - Supplier + Accumulator + Combiner
İmzası şöyle.
<R> R collect(Supplier<R> supplier,
              BiConsumer<R, ? super T> accumulator,
              BiConsumer<R, R> combiner);
Accumulator ve Combiner BiConsumer tipinden. Collector yerine kendimiz yazmak istersek, lambda kullanabiliriz ya da sınıfımızın bir metodunu çağırabiliriz. Bu metod paralelleştirme varsa işe yarar. Açıklaması şöyle. Yani iki thread'in çıktısını birleştirmek için kullanılır.
The first argument is a supplier that supplies an empty array list for adding collected stuff into. The second argument is a biconsumer that consumes each element of the array. The third argument is there only to provide parallelism support. This enables it to collect the elements into multiple array lists at the same time, and it asks you for a way to connect all these array lists together at the end.
combiner için açıklama şöyle
combiner - an associative, non-interfering, stateless function that accepts two partial result containers and merges them, which must be compatible with the accumulator function. The combiner function must fold the elements from the second result container into the first result container.
Örnek
Şöyle yaparız.
ArrayList<Integer> collected = Stream.of(1,2,3)
    .collect(
        ArrayList::new, 
        ArrayList::add, 
        ArrayList::addAll);
System.out.println(collected);
Örnek
Şöyle yaparız.
Path path = ...;
List<String> lines = Files.lines(path)
  .collect(
    ArrayList::new, 
    new BiConsumer<ArrayList<String>, String>() {
      @Override
      public void accept(ArrayList<String> lines, String line) {
      ...                  
      }
    }, 
    ArrayList::addAll
);
Örnek
 Şöyle bir collector sınıfımız olsun.
// Averager.java from the official Java tutorial
public class Averager
{
  private int total = 0;
  private int count = 0;


  public void addcount(int i) { total += i; count++;}
  public void combine(Averager other) {
    total += other.total;
    count += other.count;
  }
}
Kendi metodlarımızı çağırmak istersek şöyle yaparız. Bir Averager nesnesi yaratılır. Her eleman için addCount metodu çağrılır. addAccount bir accumulator metodudur. Stream elemanını bir result container nesnesine ekler. combine bir combiner metodudur. İki tane result container nesnesini birleştirir.
List<Integer> list = new LinkedList<Integer>();
...
Averager averageCollect = list.stream()
      .collect(Averager::new, Averager::addcount, Averager::combine);
Eğer lambda kullanmak istersek şöyle yaparız.
Averager averageCollect = list.stream()
  .collect(Averager::new, (a,b) -> a.addcount(b), (a,b) -> a.combine(b));

Hiç yorum yok:

Yorum Gönder