14 Kasım 2021 Pazar

Collectors.teeing metodu - Stream'i İki Farklı Collector'a Verir

Giriş
Java 12 ile geliyor. Her elemanı iki tane downstream collector'a verir. Bunların sonuçlarını alır ve merge function ile birleştirir. Dolayısıyla bizi Custom Collector yazmaktan kurtarır. 

Açıklaması şöyle. Yani teeing() aslında bir composite. Tüm kodda önenli olan şey en son çıktı olarak kullandığımız nesnenin iki tane sonuç alacak şekilde olması
Returns a Collector that is a composite of two downstream collectors. Every element passed to the resulting collector is processed by both downstream collectors, then their results are merged using the specified merge function into the final result.

The resulting collector functions do the following:

* supplier: creates a result container that contains result containers obtained by calling each collector’s supplier

* accumulator: calls each collector’s accumulator with its result container and the input element

* combiner: calls each collector’s combiner with two result containers

* finisher: calls each collector’s finisher with its result container, then calls the supplied merger and returns its result.
Örnek
Şöyle yaparız. Burada ilk collector toplamı buluyor, ikinci collector nesneleri sayıyor, son merge metodu ise her iki collector'ın sonuçlarını alıp ortalamayı buluyor
double mean = Stream.of(1, 2, 3, 4, 5)
  .collect(Collectors.teeing(
    summingDouble(i -> i),
    counting(),
    (sum, n) -> sum / n));

System.out.println(mean);
Örnek
Elimizde şöyle bir kod olsun. Bu bizin en son çıktımızı temsil ediyor. Dolayısıyla constructor içine iki parametre alıyor
public class PriceAndRows {

    private BigDecimal price;                             
    private final List<CartRow> rows = new ArrayList<>();  

    PriceAndRows(BigDecimal price, List<CartRow> rows) {
        this.price = price;
        this.rows.addAll(rows);
    }

    PriceAndRows() {
        this(BigDecimal.ZERO, new ArrayList<>());
    }
}
Şöyle yaparız
public PriceAndRows getPriceAndRows(Cart cart) {
  return cart.getProducts()
      .entrySet()
      .stream()
      .map(CartRow::new)                           // 1
      .collect(Collectors.teeing(                  // 2
          Collectors.reducing(                     // 3
              BigDecimal.ZERO,                     // 4
              CartRow::getRowPrice,                // 5
              BigDecimal::add),                    // 6
          Collectors.toList(),                     // 7
          PriceAndRows::new                        // 8
      ));
}
Açıklaması şöyle
1 Map each Entry to a CartRow
2. Call the teeing() method
3. The first collector computes the price. It’s a simple reducing() call, with:
4. The starting element
5. A function to extract a Price from a CartRow
6. A BinaryOperator to add two prices together
7. The second collector aggregates the CartRow into a list
8. Finally, the last parameter creates a new object that aggregates the results from the first and the second collector
Örnek
Şöyle yaparız.
Object[] array = list.stream()
    .collect(Collectors.teeing(
        Collectors.reducing(1, a -> (Integer)a[0], (a,b) -> a * b),
        Collectors.mapping(a -> (String)a[1], Collectors.joining()),
        (i,s) -> new Object[] { i, s}
    ));



Hiç yorum yok:

Yorum Gönder