21 Mayıs 2020 Perşembe

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 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 ekleme 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
Stream Sınıfı Terminal Operations yazısına taşıdım.

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())
);
count metodu
Stream Sınıfı Terminal Operations yazısına taşıdım.

distinct metodu
distinct metodu yazısna taşıdım.

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
forEach metodu yazısına taşıdım.

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
limit metodu yazısına taşıdım

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
Stream Sınıfı Terminal Operations yazısına taşıdım.

of metodu
Stream Yaratma Metodları yazısına taşıdım.

onClose metodu
Stream kapatılınca çağrılır.
Each mapped stream is closed after its contents have been placed into this stream.
Açıklaması şöyle.
Close handlers are run when the close() method is called on the stream, and are executed in the order they were added.
Örnek  - flatMap
Stream'i kapatan bazı metodlar var. Mesela flatMap. Şöyle yaparız. Dosya işlenince silinir.
Stream.generate(...).takeWhile(Objects::nonNull)
  .flatMap(file -> {
      Path p = file.toPath();
      return Files.lines(p, Charset.defaultCharset()).onClose(() -> ...);
    })
  .forEach(System.out::println);
Örnek - flatMap
Şöyle yaparız.
// example stream
Stream<String> original=Stream.of("bla").onClose(()->System.out.println("close action"));

// this is the trick
Stream<String> autoClosed=Stream.of(original).flatMap(Function.identity());
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
reduce metodu yazısına taşıdım.

sequential metodu
Örnek
Şöyle yaparız.
List<CSVRecord> recordList =  ...;
List<SiebelRecord> siebelRecords = recordList
  .stream()
  .sequential()
  .map(...)
  .collect(Collectors.toList());
skip metodu
skip metodu yazısına taşıdım.

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
takeWhile metodu yazısına taşıdım

toList metodu
toList metodu yazısına taşıdım

Hiç yorum yok:

Yorum Gönder