Java 8 — Stream

Stream kelimesini ilk duyduğum zaman aklıma Java I/O paketinde bulunan InputStream ve OutputStream gelmişti. Fakat bunun böyle olmadığını api dökümanını inceleyince fark ettim. Bu yazıda streamler nasıl çalışır , türleri nelerdir ve nasıl kullanılır sorularını cevaplamaya çalışacağım.

Stream ler fonksiyonel programlama da kullanılan Monad tasarım kalıplarına çok benzemektedir. Türkçe kelime anlamı akıştır. Bir dizi öge üzerinde hesaplamalar yapmak ve farklı türde operasyonlar yapmamızı sağlarlar.

Nasıl çalışır?

Bir stream aslında iki türlü işlem yapar. Bunlar ara işlemler ve sonlandırıcı işlemlerdir. Ara işlemler işlemin sonucunda Stream dönerken sonlandırıcı işlemler void yada stream olmayan türde değer döner.

List<String> list =
Arrays.asList(“ali”, “veli”, “ahmet”,”mehmet”);
list
.stream()
.filter(s -> s.startsWith(“a”))
.map(String::toUpperCase)
.forEach(System.out::println);
Output:
ALI
AHMET

Örnek olarak yukarıdaki koda baktığımız zaman bir liste içerisinde bulunan ali, veli, ahmet ve mehmet değerlerini ara işlem olan filter ve map methodu ile işleme alıp sonlandırıcı işlem olan forEach methoduyla konsola çıktılarını basmaktadır. Stream’in tüm ara ve sonlandırıcı işlemlerine buradan erişebilirsiniz.

Türleri nelerdir?

Streamler ikiye ayrılır. Bunlar stream() ve parallelStream() dir. stream() methodu bir listede bulunan değerlerin işleme alınmasında sıralı olarak hareket eder. Fakat parallelStream() methodu ise liste de bulunan değerleri birbirinden bağımsız olarak işleme alır. Örnek olarak yukarıda tanımlamış olduğumuz örnek listemizi stream() ve parallelStream() methodlarını ayrı ayrı kullanarak çalıştırırsak stream() methodu her zaman bize aşağıdaki sonucu dönecektir.

Output:
ALI
AHMET

Fakat parallelStream() methodu ise ilk değer olarak ALI değerini önce dönerken bazende AHMET değerini önce dönecektir. parallelStream() ‘ e yazının ilerleyen kısımlarında daha detaylı değineceğiz.

Yukarıdaki örnek de bir stream oluşturmak için List içerisindeki değerleri .stream() ile işleme almıştık. Aslında buna ihtiyaç duymadan Stream.of() methodu ilede aynı işlemi gerçekleştirebiliriz. Örnek olarak :


Stream.of(“ali”, “veli”, “ahmet”,”mehmet””)
.filter(s -> s.startsWith(“a”))
.map(String::toUpperCase)
.forEach(System.out::println);
Output:
ALI
AHMET

Java 8 ile ayrıca primitive type lara özgü stream türleride bulunmaktadır. Örneğin int , double ve long primitive türleri için IntStream , DoubleStream ve LongStream türleri bulunmaktadır.

IntStreamler for döngüsü yerinede kullanabiliriz. Aşağıdaki örnek de for döngüsü ile yapılan bir işlemin IntStream ile yapılmasını göreceğiz.

For döngüsü :

for (int i = 0 ; i < 10 ; i++){
System.out.print(i);
}
Output:
0123456789

IntStream :

IntStream.range(0,10).forEach(System.out::print);Output:
0123456789

Primitive stream ler aritmetik işlemler olan sum , average , max , min işlemlerinin kolaylıkla yapılmasını sağlarlar. Örnek olarak :

System.out.println(IntStream.range(0,10).max().getAsInt());
System.out.println(IntStream.range(0,10).min().getAsInt());
System.out.println(IntStream.range(0,10).sum());
System.out.println(IntStream.range(0,10).average().getAsDouble());
Output:
9 //max
0 //min
45 //sum
4.5 //average

Ayrıca primitive streamler obje dönüşümlerinde de kullanılabilir. Örnek olarak :

IntStream.range(0,3)
.mapToObj(i -> “ali”+i).
forEach(System.out::println);
Output:
ali0
ali1
ali2

Stream’in ikinci türü olan parallelStream ise işleme alınan değerleri sıralı olarak değilde birbirlerinden bağımsız olarak işleme alırlar. Bunu yaparken ForkJoinPool arayüzünün sağlamış olduğu commonPool methodunu kullanır. Thread pool da default tanımlı olan thread adedi kadar olan işlemleri paralel olarak çalıştırabilir.

Arrays.asList(“ali”, “veli”, “ahmet”)
.parallelStream()
.filter(s -> {
System.out.format(“Filter: %s [%s]\n”,
s, Thread.currentThread().getName());
return true;
})
.map(s -> {
System.out.format(“Map: %s [%s]\n”,
s, Thread.currentThread().getName());
return s.toUpperCase();
})
.forEach(s -> System.out.format(“ForEach: %s [%s]\n”,
s, Thread.currentThread().getName()));
Output:
Filter: ali [ForkJoinPool.commonPool-worker-1]
Map: ali [ForkJoinPool.commonPool-worker-1]
ForEach: ALI [ForkJoinPool.commonPool-worker-1]
Filter: veli [main]
Map: veli [main]
Filter: ahmet [ForkJoinPool.commonPool-worker-2]
Map: ahmet [ForkJoinPool.commonPool-worker-2]
ForEach: AHMET [ForkJoinPool.commonPool-worker-2]
ForEach: VELI [main]

Yukarıdaki örnek de parallelStream in nasıl çalıştığını daha iyi görebilirsiniz.

Özetle Java programlama dili, Java 8 versiyonunda yayınlamış olduğu stream ler ile yazılan kodların daha kolay okunup , güzel görünmesinin yanında performans açısından da hızlı olmasını sağlamıştır.

--

--

--

Software Engineer www.arifpehlivan.com

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Arif PEHLİVAN

Arif PEHLİVAN

Software Engineer www.arifpehlivan.com

More from Medium

Functional Programming In Java

JAVA /Interface

Why Spring Boot is called opinionated?

Print a sequence using 3 threads | Java