29 Temmuz 2018 Pazar

Stream Arayüzü

Giriş
Şu satırı dahil ederiz.
import java.util.stream.Stream;
Side Effect
Stream yani yan etkisi (side effect) olacak şekilde kullanılmamalı. Açıklaması şöyle

Side-effects

Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
If the behavioral parameters do have side-effects, unless explicitly stated, there are no guarantees as to the visibility of those side-effects to other threads, nor are there any guarantees that different operations on the "same" element within the same stream pipeline are executed in the same thread. Further, the ordering of those effects may be surprising. Even when a pipeline is constrained to produce a result that is consistent with the encounter order of the stream source (for example, IntStream.range(0,5).parallel().map(x -> x*2).toArray() must produce [0, 2, 4, 6, 8]), no guarantees are made as to the order in which the mapper function is applied to individual elements, or in what thread any behavioral parameter is executed for a given element.
Örnek
Elimizde şöyle bir kod olsun
String sentence = "Hi, this is just a simple short sentence";
String[] split = sentence.split(" ");
Şöyle yaparsak yan etki oluşturduğumuz için kodun doğru sırada çalışacağını garanti edemeyiz.
AtomicInteger atom = new AtomicInteger(0);
String result = Arrays.stream(split)
    .map(i -> atom.getAndIncrement()%2==0 ? i : i.toUpperCase())
    .collect(Collectors.joining(" "));
Örnek
Elimizde şöyle bir kod olsun. ArrayList'e eklemek yaptığı için yan etkiye sahip.
ArrayList<String> results = new ArrayList<>();
 stream.filter(s -> pattern.matcher(s).matches())
       .forEach(s -> results.add(s));  // Unnecessary use of side-effects!
Düzeltmek için şöyle yaparız.
List<String>results =
         stream.filter(s -> pattern.matcher(s).matches())
               .collect(Collectors.toList());  // No side-effects!
anyMatch metodu
Şöyle yaparız.
String[] array = {"a", "b", "c"};
String target = "a";
boolean result = Arrays.stream(array).anyMatch(s -> s.equals(target));
close metodu
Açıklaması şöyle.
Streams have a BaseStream.close() method and implement AutoCloseable. Operating on a stream after it has been closed will throw IllegalStateException. Most stream instances do not actually need to be closed after use, as they are backed by collections, arrays, or generating functions, which require no special resource management. Generally, only streams whose source is an IO channel, such as those returned by Files.lines(Path), will require closing. If a stream does require closing, it must be opened as a resource within a try-with-resources statement or similar control structure to ensure that it is closed promptly after its operations have completed.
Yani bir stream kapatılabilir ancak çoğu zaman gerek kalmıyor. Şöyle yaparız.
stream.close();
collect metodu
Stream Sınıfı Terminal Operations yazısına taşıdım.

concat metodu
İki stream'i birleştirerek yeni bir Stream döndürür. İmzası şöyle.
static <T> Stream<T> concat(Stream<? extends T> a,
                            Stream<? extends T> b)
Örnek
Elimizde bir stream ve bir collection olsun. Collection'ı sadece vakti gelince üretmek isteyelim. Şöyle yaparız.
return Stream.concat(
  firstStream, 
  Stream.of(Boolean.TRUE)
    .flatMap(ignoredBoolean -> expensiveCollectionCreation().stream())
);
empty metodu
Stream Yaratma Metodları yazısına taşıdım.

filter metodu
Stream Sınıfı Filtre Metodları yazısına taşıdım.

findAny metodu
Stream Search Metodları yazısına taşıdım.

findFirst metodu
Stream Search Metodları yazısına taşıdım.

forEach metodu
Açıklaması şöyle.
The behavior of this operation is explicitly nondeterministic
generate metodu
Stream Yaratma Metodları yazısına taşıdım.

iterate metodu - seed + unary operator
Stream Yaratma Metodları yazısına taşıdım.

iterator metodu
Stream elemanları tek tek dolaşmak için iterator sunar.
Örnek
Şöyle yaparız
Iterator<String> iterator = stream.iterator();
while (iterator.hasNext()) {
    String element = iterator.next();
    // Use element
}
Örnek
iterator() metodu Stream.of() ile yartılmışsa aynı sırayı muhafaza eder. Şu kod ile bunu görebiliriz.
Stream.of(a, b, c).parallel().map(Object::toString).iterator();
limit metodu
Açıklaması şöyle.
An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result. A terminal operation is short-circuiting if, when presented with infinite input, it may terminate in finite time.
Limit belirtilen sayıya kadar çalışır. Eğer Stream daha az sayı üretiyorsa takılabilir.
Örnek
Şöyle yaparız.
String[] limit = Stream.generate(() -> "test") // returns an infinite stream
                       .limit(20)
                       .toArray(String[]::new);
Örnek
Bu örnekte 10 taneden az sayı üretildiği için kod takılıyor.
List<Integer> integer = Stream.generate(new Supplier<Integer>() {
    int i = 0 ;

    @Override
    public Integer get() {
        return ++i;
    }
}).filter(j -> j < 5).limit(10).collect(Collectors.toList());
Örnek
Şöyle yaparız
final Stream stream = list.stream()
        .sorted(comparator);

if (maxLimit > 0) {
  stream = stream.limit(maxLimit);
}

return stream.collect(Collectors.toList());
skip () ve limit birbirine ters metodlar. Birisi baştaki eleman sayısını sınırlar, diğeri ise baştaki elemanları atlar.
Eğer stream'den belli sayıda elemanı atlamak istersek şöyle bir yardımcı metod kullanabiliriz.
public static <T> void skip(Stream<T> stream, int n) {
    stream.limit(n).forEach(t -> {});
}
map metodu
Stream Sınıfı Dönüşüm Metodları yazısına taşıdım.

mapToDouble metodu
Stream Sınıfı Dönüşüm Metodları yazısına taşıdım.

mapToInt metodu
Stream Sınıfı Dönüşüm Metodları yazısına taşıdım.

min metodu
Stream'in boş olma ihtimaline karşı Optional döner. Bir Comparator alır. Şöyle yaparız.
Optional<Date> min = list.stream()
.min((b1,b2 ) -> b1.compareTo(b2));
Nesnenin compareTo metodu varsa kendi lambdamızı yazmak yerine kullanmak gerekir. Şöyle yaparız.
Optional<Integer> minimal = list.stream().min(Integer::compareTo);
max metodu
Stream'in boş olma ihtimaline karşı Optional döner. Bir Comparator alır. Şöyle yaparız.
List<Integer> list = Arrays.asList(5,3,8);
Optional<Integer> op = list.stream().max((a, b) -> {
  int compare = Integer.compare(a, b);
  return compare;
});
noneMatch metodu
Şöyle yaparız.
int root = ...;
boolean isPrime = IntStream
  .rangeClosed(2, root)
  .noneMatch(n -> n == 0);
of metodu
Stream Yaratma Metodları yazısına taşıdım.

onClose metodu
Stream kapatılınca çağrılır.
Stream<String> original=Stream.of("bla").onClose(()->System.out.println("..."));
Stream'i kapatan bazı metodlar var. Mesela flatMap
Each mapped stream is closed after its contents have been placed into this stream.
peek metodu
Tüm elemenlar için çağrılır.forEach() ile benzer ancak esas amacı debug içindir. Açıklaması şöyle.
This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline
Örnek
Şöyle yaparız.
"abcd".chars().peek(e->System.out.print(e + ":"))
Çıktı olarak şunu alırız.
a:b:c:d:
Örnek
Peek elemanları yazdırmak için kullanılabilir. Şöyle yaparız.
Stream.of("one", "two", "three", "four")
  .filter(e -> e.length() > 3)
  .peek(e -> System.out.println("Filtered value: " + e))
  .map(String::toUpperCase)
  .peek(e -> System.out.println("Mapped value: " + e))
  .collect(Collectors.toList());
Örnek
Esas amacı elemanı değiştirmek değil, ancak bir elemanın setter metodunu çağırmak için kullanılabilir.
List<Foo> newFoos = foos.stream()
            .filter(Foo::isBlue)
            .peek(foo -> foo.setTitle("Some value"))
            .collect(Collectors.toList());
Örnek
Kalan yüzdeyi yazdırmak için kullanılabilir. Şöyle yaparız.
Stream<MyData> myStream = readData();
final AtomicInteger loader = new AtomicInteger();
int fivePercent = elementsCount / 20;
MyResult result = myStream
  .map(row -> process(row))
  .peek(stat -> {
    if (loader.incrementAndGet() % fivePercent == 0) {
      System.out.println(loader.get() + " elements on " + elementsCount + " treated");
      System.out.println((5*(loader.get() / fivePercent)) + "%");
    }
  })
  .reduce(MyStat::aggregate);
reduce metodu - Accumulator
İmzası şöyle.
Optional<T> reduce(BinaryOperator<T> accumulator);
reduce metodu - Identity + Accumulator + Combiner
İmzası şöyle.
<U> U reduce(U identity,
             BiFunction<U, ? super T, U> accumulator
             BinaryOperator<U> combiner);
skip metodu
Şöyle yaparız.
List<String> tokens = ...;

tokens.stream().skip(1).forEach(token -> ...);

splitIterator metodu
Şöyle yaparız.
Stream<String> stream = Stream.of("a", "b", "c").limit(2);
Spliterator<T> spliterator = stream.spliterator();
sorted metodu
sorted metodu yazısına taşıdım.

takeWhile metodu
Java 9 ile geliyor. Belli bir koşuldan sonra Stream'i dolaşmayı durdurur.
List<Integer> integer = Stream.generate(new Supplier<Integer>() {
    int i = 0 ;

    @Override
    public Integer get() {
        return ++i;
    }
}).takeWhile(j -> j < 5).limit(10).collect(Collectors.toList());


Hiç yorum yok:

Yorum Gönder