Stream API (J2SE8) mimarisi ve kullanım teknikleri: Bölüm-1

Herkese merhaba;

Bu makale ile Java 8 standartı olan stream api mimarisi hakkında sizlere bilgi vermeye çalışacağım. Öncelikle stream api ile ilgili bilinmesi gereken birtakım temel özelliklere değinelim:

Amaç: Yığınsal da denilen dizileri listeleri düzenlemey yarayan bir apidir. Bunlara örnek olarak primitive veya obje diziler olan int[] veya String[] gibi modeller veya JCF de bahsi geçen Collection interface inden genişleyen ArrayList, HashSet, LinkedHashMap, List, Set vs tüm bu örnek tiplere müdehaleyi kolaylaştıran bir API dir.

Örnek kullanım biçimlerine değinecek olur isek temel dizi bileşenlerinden başlayabiliriz:

Önce temel bir dizi bileşeni oluşturalım:

Ön izlem:
String listenin Lambda ve Stream api kullanılarak yazdırılması.
Şimdi diziyi Stream e çevirelim: Şimdi son olarak Stream api si ile gelen forEach döngüsü ile verileri görüntüleyelim:
islemdizisi.forEach(basliklar ->{
			System.out.println("Başlık:"+ basliklar);
			
		}); 
Burada anlamamız gereken birtakım nesneler ve komutlar var: 1. Stream(): Bu bir interface dir ve BaseStream i extend etmiştir. Generik bir yapıya sahiptir. Stream objelerinin barındırılması için nesnemizi bu tip ile tanımlıyoruz. 2. ForEach: Bu komut bir stream içinde elemanlar arası döngü ile geçişi sağlamaktadır. İçinde Lambda tanımlama biçimlerini destekleyen bir döngü modelidir. 3. Basliklar ->{ System.out.println(“Başlık:”+ Basliklar);} : ForEach ile listeden gelen değişken tipini otomatik olarak tanımlar ve bu kullanım biçimi ile 1 değişken alır kendi scope una ( {} alanı : scope). Döngü ile her dönüşte içindeki liste elemanı Baslik değişkenine atanır. İçeride ise bu değişken kullanılır. Inner Class veya Pojo ile Kullanımı: Öncelikle StreamOrnek.class ismi ile bir sınıf oluşturuyorum, içine de class tanımı yapıyorum:
class StreamOrnek {
	public class ornekPojo{
		private Long id;
		private String ad;
		private String soyad;
		private String tc;
		public Long getId() {
			return id;
		}
		public void setId(Long id) {
			this.id = id;
		}
		public String getAd() {
			return ad;
		}
		public void setAd(String ad) {
			this.ad = ad;
		}
		public String getSoyad() {
			return soyad;
		}
		public void setSoyad(String soyad) {
			this.soyad = soyad;
		}
		public String getTc() {
			return tc;
		}
		public void setTc(String tc) {
			this.tc = tc;
		}
       }
}
İç sınıflar (inner class) erişim için kullanılan yöntemlerden biri şöyledir:
StreamOrnek.ornekPojo obj1  =  new StreamOrnek().new ornekPojo();
Burada önce Ana sınıf yazılır ardından alt sınıf adı belirtilir. (Android de R classı örneği gibi.) Şimdi bu sınıflardan örnek objeler yaratalım:
		StreamOrnek.ornekPojo obj1  =  new StreamOrnek().new ornekPojo();
		obj1.setId(1L);
		obj1.setAd("Selçuk");
		obj1.setSoyad("Uzunsoy");
		obj1.setTc("12345678910");
	
		StreamOrnek.ornekPojo obj2  =  new StreamOrnek().new ornekPojo();
		obj2.setId(2L);
		obj2.setAd("R2D2");
		obj2.setSoyad("Starwars");
		obj2.setTc("1010101010101010");
Yarattığımız bu objeleri şimdi diziye atalım ve bu diziyi stream e çevirelim: Dönüşüm zamanı : ) Stream içindeki sınıf tanımlamasına odaklanın: Stream burada Stream içinde artık inner class ın olduğunu generik tip tanımlama ile belirtiyoruz. Bu tip tanımlandıktan sonra foreach ile bu nesneleri yazdırabilirim:
islemdizisi_pojo.forEach(obj ->{
			System.out.println("ID:"+ obj.getId());
			System.out.println("İsim:"+ obj.getAd());
			System.out.println("Soyisim:"+ obj.getSoyad());
			System.out.println("TC:"+ obj.getTc());
});
Buradaki obj ifadesi otomatik olarak StreamOrnek.ornekPojo ya cast edilecek. (Lambda ifadeleri ) Bu sayede tip güvenliği sağlanmı şoluyor. Peki bunu başka şekilde nasıl yazdırabiliriz ? Eğer bir method :: “iki nokta üst üste operatörü” ile bir sınıftan çağırılır ise method ismini verdiğimizde, parametresi giden obje türünden olan method çağırılacaktır. Mesela: islemdizisi_pojo.forEach(StreamOrnek::yazdir); StreamOrnek içinde yazdır adında bir parametreli bir method tanımlıyoruz:
	public static void yazdir(StreamOrnek.ornekPojo veri){		
		System.out.println("Bilgi Pojo kullanımı:"+veri.getAd());
	}
Peki şimdi objeyi listeye koyduk ama içinden bir seçim yapmak istiyorsam ne yapmalıyım ? Mesela objenin bir parametresi kayıt edilen ismi veriyor. Bu bana istediğim ismi arama şansı veriyor mu acaba ? Burada liste içinde kayıtlı objelerden adında R2D2 olan objeler gelmesi için Predicate functional Interface inden faydalanıyoruz. Bu tip bir koşul Lambda betiği yazarak filter komutu aracığı ile liste içindeki verileri süzüyoruz. Şimdi sıra yazdırmada:
filtrelenmis_islemdizisi_pojo.forEach(StreamOrnek::yazdir);
yazdır methodunun parametresi , kullandığımız objenin tipindeydi ! Stream tek kullanımlık bir yapıya sahiptir. Bir kere kullanıldığında yeniden stream yaratmanız gerekir:
islemdizisi_values = dizi_values.stream();
Dizi içindeki istediğim değer aralığını Predicate ile belirliyorum:
Ön izlem:
Sayısal içerikli bir listenin Stream filtre kullanılarak veri setinin kısıtlandırılması.
Burada 6 dan küçük değerler filtrelenmesi için ön hazırlık yapıyorum. filter komutunu kullanarak gerekli şekilde eleme işlemini yaptırıyoruz. Şimdi method referansı ile otomatik olarak yazdırmak için Integer parametresi alan bir yazdır methodu yazıyorum:
	public static void yazdir(Integer veri){		
		System.out.println("Bilgi"+veri);
	}
Bu methodu forEach içinde kullarak otomatik olarak çağırılmasını sağlıyorum:
filtrelenmis_islemdizisi_values.forEach(StreamOrnek::yazdir);
Eğer verilerin tekrarlı olanlarını listeden elemek istiyor isem, distinct komutunu kullanmalıyım: Eğer otomatik olarak küçükten büyüğe doğru ASC sıralama bazlı bir çıktı almak istiyor isem: NOT: Eğer sıralamayı obje özelliklerine göre yapmak istiyor iseniz Comparator Interface inden yararlanmalısınız. Eğer gelen veriler içinden kısıtlı sayıda gösterim yapmayı istiyor iseniz limit komutu tam size göre: Eğer listesinin açık aralıklı adedini “[ ) küme gösterimi” istiyor iseniz count kullanılır: Stream api yapısının oldukça fazla özelliği mevcut ama ben genelde en çok kullanılan özelliklerine ilk Stream api makalemde değinmiş oldum. Umarım yararlı bulmuşsunuzdur. iyi çalışmalar, bol tekrarlı günler 🙂
  Örnek kodları indir:
  Proje Dosyası
GIT Repository:
Adres: https://github.com/uzunsoy/stream_api_bolum_1.git

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir