# Stream API
JDK 8 ile lambda ifadelerinin Javaâya eklenmesi üzerine, yine bununla ilintili olarak Stream API yazılmıÅtır. Basitçe söylemek gerekirse, koleksiyonlar üzerinde lambda ifadeleri kullanarak iÅlem yapmamızı saÄlayan metotlar eklemiÅtir.
Stream, akıŠdemektir. Nesnelerin art arda gelmesiyle bir akıŠoluÅur. AkıŠyaratarak, bir dizi veya koleksiyonun elemanları üzerinde iÅlemler yapabiliriz. AkıÅlar, verinin nasıl depolanacaÄıyla ilgilenmez, yalnızca veriyi bir yerden bir yere transfer eder. Bu transfer esnasında veri üzerinde bir veya birden fazla iÅlem yapılması muhtemeldir. Bu iÅlem verinin filtrelenmesi, sıralanması veya dönüÅtürülmesi gibi iÅlemler olabilir. Bu iÅlem, akıÅın kaynaÄını deÄiÅtirmez; fakat yeni bir akıŠoluÅturur. ÃrneÄin, bir akıÅın içindeki nesneleri sıralarsanız, kaynak deÄiÅmez; fakat sıralı nesnelerden oluÅan yeni bir akıŠyaratılır.
JDK 8 ile akıÅları, Stream türünde bir nesne olarak ifade edebiliriz. Stream API çok kapsamlı bir konu olsa da biz yalnızca koleksiyonlar üzerinde yapılan iÅlemleri inceleyeceÄiz.
Bir koleksiyonun akıÅını elde edebilmek için, JDK 8 ile _Collection_ arayüzüne _stream()_ adında yeni bir metot eklenmiÅtir. Bu metodun yapısı aÅaÄıdaki gibidir:
```java
interface Collection
{
Stream stream();
}
```
Bu metodu kullanarak bir koleksiyon için yeni bir akıŠoluÅturabiliriz. Bu metot her çaÄrıldıÄında koleksiyon üzerinde yeni bir akıŠoluÅturulur.
Åimdi _Stream_ arayüzünün en çok kullanılan metotlarını inceleyelim. Bu metotların hepsinde aynı listeyi kullanacaÄız. Ãnce bu listeyi oluÅturalım:
```java
ArrayList list = new ArrayList<>();
list.add(25);
list.add(12);
list.add(3);
list.add(89);
list.add(25);
list.add(44);
list.add(100);
list.add(7);
list.add(63);
```
### forEach()
Bu metodu kullanarak akıÅın bütün elemanları üzerinde bir iÅlem yapabilirsiniz. _Consumer_ türünde bir parametre alır. Bu metot akıÅı sonlandıran bir metottur, yani bu metodu kullandıktan sonra akıŠüzerinde baÅka bir iÅlem yapamazsınız.
```java
list
.stream()
.forEach(number -> System.out.println(number));
```
GördüÄünüz gibi, forEach() metodunu kullanarak akıÅın bütün elemanlarını konsola yazdırıyoruz. Bu kodu çalıÅtırdıÄınız zaman çıktısı aÅaÄıdaki gibi olur:
```java
25
12
3
89
25
44
100
7
63
```
### filter()
Bu metodu kullanarak akıÅın elemanlarını filtreleyebilirsiniz. Predicate türünde bir parametre alır. Bu teste uymayan elemanları akıÅa almaz.
```java
list
.stream()
.filter(number -> number > 60)
.forEach(number -> System.out.println(number));
```
Burada, filter() metodunu kullanarak yalnızca 60âdan büyük sayıların konsola yazdırılmasını istiyoruz. Bu kodu çalıÅtırdıÄınız zaman çıktısı aÅaÄıdaki gibi olur:
```java
89
100
63
```
### distinct()
Bu metodu kullanarak akıÅın içinde her elemanın en fazla 1 kez yer almasını saÄlayabilirsiniz. EÄer akıÅın içinde bir eleman daha önce tanımlanmıÅsa, ikinci kez yer almaz. Parametre almaz.
```java
list
.stream()
.distinct()
.forEach(number -> System.out.println(number));
```
Bu kodu çalıÅtırırsanız, listeye iki kez eklenen 25 sayısının yalnızca bir kez konsola yazdırıldıÄını görürsünüz:
```java
25
12
3
89
44
100
7
63
```
### sorted()
Bu metodu kullanarak akıÅın elemanlarını sıralayabilirsiniz.
```java
list
.stream()
.sorted()
.forEach(number -> System.out.println(number));
```
Bu kodu çalıÅtırdıÄınız zaman çıktısı aÅaÄıdaki gibi olur:
```java
3
7
12
25
25
44
63
89
100
```
Bu metodun _Comparator_ türünde bir parametre alan baÅka bir versiyonu daha vardır. Bu versiyonu kullanarak akıÅın sıralama algoritmasını deÄiÅtirebilirsiniz.
```java
list
.stream()
.sorted(Comparator.reverseOrder())
.forEach(number -> System.out.println(number));
```
ÃrneÄin, bu kodu çalıÅtırırsanız, elemanların büyükten küçüÄe doÄru sıralanarak konsola yazdırıldıÄını görürsünüz:
```java
100
89
63
44
25
25
12
7
3
```
### limit()
Bu metodu kullanarak akıŠüzerinde gerçekleÅtireceÄiniz iÅlemleri belli bir sayıyla sınırlandırabilirsiniz. **long** türünde bir sayıyı parametre olarak alır.
```java
list
.stream()
.limit(5L)
.forEach(number -> System.out.println(number));
```
Bu kodu çalıÅtırırsanız, yalnızca ilk 5 elemanın konsola yazdırıldıÄını görürsünüz:
```java
25
12
3
89
25
```
### skip()
Bu metodu kullanarak akıÅın belli sayıda elemanını atlayabilirsiniz. Bu elemanlar üzerinde iÅlem yapılmaz. long türünde bir sayıyı parametre olarak alır.
```java
list
.stream()
.skip(5L)
.limit(2L)
.forEach(number -> System.out.println(number));
```
Burada, akıÅın ilk 5 elemanını atlıyor ve sonraki 2 elemanı konsola yazdırıyoruz:
```java
44
100
```
### count()
Bu metodu kullanarak akıÅtaki eleman sayısını öÄrenebilirsiniz. Bu metot akıÅı sonlandıran bir metottur, yani bu metodu kullandıktan sonra akıŠüzerinde baÅka bir iÅlem yapamazsınız.
```java
long count = list
.stream()
.filter(number -> number < 40)
.distinct()
.count();
System.out.println(count);
```
Burada, listenin içinde **40**âtan küçük kaç farklı sayı olduÄunu konsola yazdırıyoruz. Bu kodu çalıÅtırırsanız konsola **4** yazar.
### anyMatch()
_Predicate_ türünde bir parametre alır ve bu testi akıÅın bütün elemanları üzerinde uygular. Elemanlardan herhangi biri bu testten geçiyorsa **true**, aksi halde **false** döndürür. Bu metot akıÅı sonlandıran bir metottur, yani bu metodu kullandıktan sonra akıŠüzerinde baÅka bir iÅlem yapamazsınız.
```java
boolean match = list
.stream()
.anyMatch(number -> number < 5);
System.out.println(match);
```
Burada, listenin içinde 5âten küçük sayı olup olmadıÄını test ediyoruz. Listede 5âten küçük yalnızca 3 vardır; fakat bu bile metodun **true** döndürmesi için yeterlidir. Bu kodu çalıÅtırırsanız konsola **true** yazar.
### allMatch()
_Predicate_ türünde bir parametre alır ve bu testi akıÅın bütün elemanları üzerinde uygular. Elemanların tamamı bu testten geçiyorsa **true**, aksi halde **false** döndürür. Bu metot akıÅı sonlandıran bir metottur, yani bu metodu kullandıktan sonra akıŠüzerinde baÅka bir iÅlem yapamazsınız.
```java
boolean match = list
.stream()
.allMatch(number -> number < 5);
System.out.println(match);
```
Bu kodu çalıÅtırırsanız konsola **false** yazar; çünkü listede 5âten büyük elemanlar da vardır.
### noneMatch()
_Predicate_ türünde bir parametre alır ve bu testi akıÅın bütün elemanları üzerinde uygular. Elemanların hiçbiri bu testten geçmiyorsa **true**, aksi halde **false** döndürür. Bu metot akıÅı sonlandıran bir metottur, yani bu metodu kullandıktan sonra akıŠüzerinde baÅka bir iÅlem yapamazsınız.
```java
boolean match = list
.stream()
.noneMatch(number -> number < 5);
System.out.println(match);
```
Bu kodu çalıÅtırırsanız konsola false yazar; çünkü listede 5âten küçük elemanlar vardır.
### map()
AkıÅın elemanlarını deÄiÅtirmek için bu metodu kullanabilirsiniz. _Function_ türünde bir parametre alır ve bu fonksiyonu akıÅın bütün elemanlarına uygular. AkıÅın yeni elemanları bu metottan dönen deÄerlerdir.
```java
list
.stream()
.map(number -> number * 2)
.forEach(number -> System.out.println(number));
```
Bu örnekte, akıÅın bütün elemanlarını 2 ile çarptık. Bu kodu çalıÅtırırsanız çıktısı aÅaÄıdaki gibi olur:
```java
50
24
6
178
50
88
200
14
126
```
Bu metodu kullanarak akıÅın içindeki elemanların türünü deÄiÅtirmek de mümkündür:
```java
list
.stream()
.map(number -> Math.sqrt(number))
.forEach(number -> System.out.println(number));
```
Burada akıÅın türünü Integerâdan Doubleâa deÄiÅtiriyoruz. Bu kodu çalıÅtırırsanız çıktısı aÅaÄıdaki gibi olur:
```java
5.0
3.4641016151377544
1.7320508075688772
9.433981132056603
5.0
6.6332495807108
10.0
2.6457513110645907
7.937253933193772
```