20 Ağustos 2019 Salı

Stream Terminal Metodları

Giriş
Terminal operations olarak adlandırılan metodlar hemen (eager)çalıştırılırlar. Bu metodlar şunlardır.
- allMatch
- anymatch
- collect
- count
- findAny
- findFirst
- forEach
- min
- max
- noneMatch
- reduce
- toArray
terminal işlemler bir kere çalıştırılabilir
terminal işlemler lazy olsalar bile tek bir kere çalıştırılabilir. Açıklaması şöyle
A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, "forked" streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.
Şu kod filter iki kere çağrıldığı için IllegalStateException fırlatır.
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints.filter(d -> d > 1.3);
ints.filter(d -> d > 2.3).forEach(System.out::println);
Doğru kullanım için şöyle yaparız
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints = ints.filter(d -> d > 1.3);
ints.filter(d -> d > 2.3).forEach(System.out::println);
veya şöyle yaparız.
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints.filter(d -> d > 1.3)
  .filter(d -> d > 2.3)
   .forEach(System.out::println);
anyMatch metodu
noneMatch() ile kardeştir
Örnek
Şöyle yaparız.
String[] array = {"a", "b", "c"};
String target = "a";
boolean result = Arrays.stream(array).anyMatch(s -> s.equals(target));
Örnek
Elimizde şöyle bir kod olsun. User listesinde yaşı 50 olan varsa bu listenin tamamını map'ten silmek isteyelim.
Map<String, List<User> myMap = new HashMap<>();
Şöyle yaparız.
myMap.entrySet()
    .removeIf(e -> e.getValue()
        .stream()
        .anyMatch(User::is50));
collect metodu
collect metodu - Supplier + Accumulator + Combiner yazısına taşıdım
collect metodu - Kendi Collector Nesnemiz yazısına taşıdım.

count metodu
count metodu yazısına taşıdım.

forEach metodu
Elimizde Flight listesi olsun. getLocation metodu bir string döndürüyor olsun. Tüm location'ları yazıdırmak için şöyle yaparız.
Stream.of(flights)
        .map(f -> f.getLocations())
        .filter(f -> f != null)
        .forEach(System.out::println);
noneMatch metodu
anyMatch() ile kardeştir
Örnek
Şöyle yaparız.
int root = ...;
boolean isPrime = IntStream
  .rangeClosed(2, root)
  .noneMatch(n -> n == 0);

reduce metodu - BinaryOperator
Örnek
Eğer identity değeri yoksa stream'deki ilk elemanı sonuç olarak döner. Örnek biraz saçma ama şöyle yaparız.
public static int countWords(String s) {
  return s.chars().reduce((x, y) -> {
    if((char)y == ' ')
      ++x;
      return x;
  }).orElse(0);
}
Girdi olarak "asd" verirsek a karakterinin int değeri olan 97 sonucunu alırız.

Örnek
Şöyle yaparız. map ile stream boolean stream'e dönüştürülür. reduce ile tüm boolean'lar "and" işlemine tabi tutulur. reduce() Optional döner. Stream boş is empty Optional döner. Bu durumda false dönmüş oluruz.
Stream<Whatever> stream = ...;
return stream.map(Whatever::someCheck).reduce(Boolean::logicalAnd).orElse(false);

reduce metodu - Identity + BinaryOperator
İmzası şöyledir. Tek bir sonuç döndürür.
<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator)
Örnek
Bir listedeki tüm elemanları çarpmak için şöyle yaparız.
listOfIntegers.stream().reduce(1, (a, b) -> a * b);
Örnek
Listedeki değerleri toplamak için şöyle yaparız.
BigDecimal total = 
  list
  .stream()
  .reduce(BigDecimal.ZERO, BigDecimal::add);
Örnek
Bir string'deki ' ' karakterini saymak için şöyle yaparız.
public static int countWords(String s) {
  return s.chars().reduce(0, (x, y) -> {
    if((char)y == ' ')
      return x + 1;
    return x;
  });
}
reduce metodu - Identity + Accumulator + Combiner
İmzası şöyle. Identity ilk başlangıç değerini belirtir. Accumulator işlem sonuçlarını biriktirir.
<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)
Örnek
Şöyle yaparız.
int sum = pojoList.stream()
                  .reduce(0, (s,ob)->s+ob.getA()+ob.getB(),Integer::sum);
Örnek
Şöyle yaparız
public float totalB() {
  return Arrays.stream(d).reduce(0.0f,(r, f) -> r + f.getB(), Float::sum);
}


Hiç yorum yok:

Yorum Gönder