Stream Arayüzü
Stream arayüzü, Java 8 ile eklenmiş, yeni bir arayüzdür. Bu arayüzün bir takım metotları yardımıyla, bir çok işlem kolaylıkla yapılabilmektedir. Java 8 ile birlikte, Collection arayüzüne Stream isimli bir metot eklenmiştir.
Collection arayüzüne eklenen bu metot ile Stream arayüzü metotlarıyla doğrudan kullanılabilir. Stream arayüzünn fonksiyonları java'da yeni model iteratör gibi düşünülebilir. Stream arayüzünün, birçok yararlı metodu bulunmaktadır. Bu metotlar, tipik olarak gerektiğinde java.util.Function paketi içerisindeki fonksiyonel arayüzleri kullanmaktadır. Stream arayüzü java.util.Stream
paketi içerisinde yer almaktadır. Stream arayüzünün Iterator'e göre kullanım farkı lambda ifadelerinin kullanılabilmesidir.
Stream Arayüzünün Filter Metodu
Filter metodu, aşağıdaki şekilde bildirilmiştir.
Stream<T> filter(Predicate<? super T> predicate)
Bu metot belirli bir koşula uygun olanları başka bir Stream referansı olarak bize vermektedir. Örneğin;
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzü
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("antalya");
cities.add("antakya");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
Stream<String> stream = cities.stream();
stream.filter(s -> {
System.out.println("filter:" + s);
return s.startsWith("an");
}).forEach(s -> {System.out.println(s);});
}
}
forEach ve Filter metodu ile ismi "an" ile başlayan tüm şehirleri ekrana basan program aşağıdaki gibi yazılabilir.
/*----------------------------------------------------------------------------------------------------------------------
filter ve forEach metotları
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void displayUpper(String s)
{
System.out.println(s.toUpperCase());
}
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("antalya");
cities.add("antakya");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
Stream<String> stream = cities.stream();
stream.filter(s -> s.startsWith("an")).forEach(App::displayUpper);
}
}
Sınıf Çalışması: Ürün bilgilerini temsil eden product isimli bir sınıf yazınız. Sınıf içerisinde ürün kodu, ürün adı, ürün ücreti ve ürün stok adeti olsun. Bir Product veri yapısı oluşturunuz. Klavyeden girilen fiyat aralığı içerisinde ve stokta olan ürünleri Stream
package org.csystem;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("123", "meyve suyu", 10, 3, LocalDate.of(2016, 3, 20), 50));
products.add(new Product("1233", "muz", 5, 1, LocalDate.of(2016, 2, 22), 20));
products.add(new Product("1234", "ton balığı", 20, 10, LocalDate.of(2016, 5, 22), 100));
products.add(new Product("1235", "Barbunya", 7, 2, LocalDate.of(2016, 6, 24), 70));
//...
double result = products.stream()
.filter(p -> p.getExpiryDate().isBefore(LocalDate.now()))
.map(p->p.getStock() * (p.getPrice() - p.getCost()))
.reduce(0.0, (acc, val)-> acc + val);
System.out.println(result);
}
}
package org.csystem;
import java.time.LocalDate;
public class Product {
private String m_id, m_name;
private double m_price, m_cost;
private LocalDate m_expiryDate;
private int m_stock;
public Product(String id, String name, double price, double cost, LocalDate expiryDate, int stock)
{
//Kontrol
m_id = id;
m_name = name;
m_price = price;
m_cost = cost;
m_expiryDate = expiryDate;
m_stock = stock;
}
public String getId()
{
return m_id;
}
public void setId(String id)
{
m_id = id;
}
public String getName()
{
return m_name;
}
public void setName(String name)
{
m_name = name;
}
public double getPrice()
{
return m_price;
}
public void setPrice(double price)
{
m_price = price;
}
public int getStock()
{
return m_stock;
}
public void setStock(int stock)
{
m_stock = stock;
}
public double getCost()
{
return m_cost;
}
public void setCost(double cost)
{
m_cost = cost;
}
public LocalDate getExpiryDate()
{
return m_expiryDate;
}
public void setExpiryDate(LocalDate expiryDate)
{
m_expiryDate = expiryDate;
}
@Override
public String toString()
{
return String.format("[%s]-%s-[%f]-%d", m_id, m_name, m_price, m_stock);
}
}
Stream Sınıfının forEach metodu
Bu metot Consumer fonksiyonel arayüz referansı kabul eder ve o Stream için belirli geri dönüş değerini tutar.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün forEach metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
cities.forEach(s -> System.out.println(s));
}
}
/*----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
cities.forEach(System.out::println);
}
}
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> referansı ile forEach metodu kullanımı
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
Stream<String> stream = cities.stream();
stream.forEach(System.out::println);
}
}
Anahtar Notlar: List arayüzü içerisinde çok sık kullanılan Stream metotları, aynı isimle ve benzer yapıda yazılmıştır, zaten bunlar da kendi içerisinde Stream referanslarını alarak Stream metotlarıyla işlem yapmaktadırlar.
Map Metodu
java<R> Stream<R> map(Function<? super T,? extends R> mapper)
Map metodu, Function fonksiyonel arayüzü parametrelidir. Bir Stream'den başka bir Stream'e doğrudan aktarmak için kullanılmaktadır.
Örneğin, bir veri yapısı içerisindeki Stringlerin büyük harfe çevirilmiş yeni bir Stream elde edilmektedir.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün map metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.csystem.utils.Keyboard;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("antalya");
cities.add("antakya");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
cities.stream().map(s -> s.toUpperCase()).forEach(System.out::println);
}
}
Yada örneğin String türünden veriler tutan bir veri yapısından her bir String'in uzunluğunu başka bir Stream'e veren program aşağıdaki gibi yazılabilir.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> map metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<String> cities = new ArrayList<>();
cities.add("ankara");
cities.add("antalya");
cities.add("antakya");
cities.add("istanbul");
cities.add("zonguldak");
cities.add("çanakkale");
cities.add("bursa");
cities.stream().map(s -> s.length()).forEach(System.out::println);
}
}
Sınıf Çalışması: Product türünden bir veri yapısı içerisinde, tüm ürünleri toplam fiyatlarından oluşan bir Stream elde ediniz ve forEach metodu ile yazdırınız.
/*----------------------------------------------------------------------------------------------------------------------
Sınıf Çalışması diğer bir çözüm
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("12345", "laptop", 3000, 10));
products.add(new Product("123", "mouse", 50, 5));
products.add(new Product("12", "Klavye", 100, 11));
products.add(new Product("123456", "Tablet", 2000, 0));
products.stream().filter(p -> {
if (p.getStock() > 0)
System.out.print(p.getName() + ":");
return p.getStock() > 0;
}).map(p -> p.getPrice() * p.getStock()).forEach(System.out::println);
}
}
Reduce Metotları
Stream arayüzünün reduce isimli 3 adet metodu bulunmaktadır.
java reduce(T identity, BinaryOperator<T> accumulator)
Şu yapıdaki metodunun 1. parametresi ilk değer, 2. parametresi BinaryOperator türünden bir fonksiyonel arayüz referansıdır.
Örneğin;
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; ++i)
list.add(i);
int sum = list.stream().reduce(0, (a, b)-> a + b);
System.out.println(sum);
}
}
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 5; ++i)
list.add(i);
int sum = list.stream().filter(val -> val % 2 == 0).reduce(0, (a, b)-> a + b);
System.out.println(sum);
}
}
Sınıf Çalışması:
Product açılımlı bir liste içerisinde son kullanma tarihi geçmemiş olan ürünlerin toplam fiyatını bulan programı Stream API kullanarak yazınız. Program aynı zamanda son kullanma tarihi geçmiş olanları da bularak kar/zarar açıklaması da yapacaktır.
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("123", "meyve suyu", 10, 3, LocalDate.of(2016, 3, 20), 50));
products.add(new Product("1233", "muz", 5, 1, LocalDate.of(2016, 2, 22), 20));
products.add(new Product("1234", "ton balığı", 20, 10, LocalDate.of(2016, 5, 22), 100));
products.add(new Product("1235", "Barbunya", 7, 2, LocalDate.of(2016, 6, 24), 70));
//...
double result = products.stream()
.filter(p -> p.getExpiryDate().isBefore(LocalDate.now()))
.map(p->p.getStock() * (p.getPrice() - p.getCost()))
.reduce(0.0, (acc, val)-> acc + val);
System.out.println(result);
}
}
Count Metodu
Stream arayüzünün Count metodu elde edilen Stream'in kaç tane elemana sahip olduğu bilgisini geri döner.
/*----------------------------------------------------------------------------------------------------------------------
Stream arayüzünün count metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; ++i)
list.add(i);
System.out.println(list.stream().filter(val -> val % 2 == 0).count());
}
}
anyMatch ve allMatch Metotları
anyMatch ve allMatch metotları parametresiyle aldığı koşula sırasıyla herhangi bir tanesi uyuyorsa ve hepsi birden koşula uyuyorsa true döndüren metotlardır.
/*----------------------------------------------------------------------------------------------------------------------
allMatch metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 2; i <= 100; i += 2)
list.add(i);
if (list.stream().allMatch(val -> val % 2 == 0))
System.out.println("Hepsi çift");
else
System.out.println("Hepsi çift değil");
}
}
/*----------------------------------------------------------------------------------------------------------------------
anyMatch metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 1; i <= 100; ++i)
list.add(i);
if (list.stream().anyMatch(val -> val % 2 == 0))
System.out.println("Çift var");
else
System.out.println("Çift değil");
}
}
noneMatch Metodu
noneMatch
metodu Stream
içerisindeki elemanların hiç bir tanesi koşula uymuyor ise true
aksi halde false
döner. Dikkat edilirse bu metot anyMatch
metodunun mantıksal değilidir.
Limit Metodu
Bu metod Stream'e verilen max eleman kadarlık kısmını almakta kullanılır.
Sınıf Çalışması: Product türünden bir listeyi karıştırınız ve klavyeden girilen n sayısı kadar ürünü ekrana yazdırınız.
package org.csystem;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("123", "meyve suyu", 10, 3, LocalDate.of(2016, 3, 20), 50));
products.add(new Product("1233", "muz", 5, 1, LocalDate.of(2016, 2, 22), 20));
products.add(new Product("1234", "ton balığı", 20, 10, LocalDate.of(2016, 5, 22), 100));
products.add(new Product("1235", "Barbunya", 7, 2, LocalDate.of(2016, 6, 24), 70));
Collections.shuffle(products);
int n = 2;
products.stream().limit(n).forEach(System.out::println);
}
}
Sınıf çalışması: Product türünden bir listeyi satış fiyatına göre azalan sırada sıralayınız ve klavyeden girilen n sayısı kadar ürünü ekrana yazdırınız
Dipnot: Burada comprator arayüzü tek bir abstract metoda sahip olduğundan fonksiyonel bir arayüz gibi kullanılabilir.
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("123", "meyve suyu", 10, 3, LocalDate.of(2016, 3, 20), 50));
products.add(new Product("1233", "muz", 5, 1, LocalDate.of(2016, 2, 22), 20));
products.add(new Product("1234", "ton balığı", 20, 10, LocalDate.of(2016, 5, 22), 100));
products.add(new Product("1235", "Barbunya", 7, 2, LocalDate.of(2016, 6, 24), 70));
Collections.sort(products, (p1, p2) -> Double.valueOf(p2.getPrice()).compareTo(p1.getPrice()));
int n = 2;
products.stream().limit(n).forEach(System.out::println);
}
}
generate Metodu
generate metodu Stream arayüzünün static bir metodudur. Bu Supplier<T>
fonksiyonel arayüzünü kullanmaktadır. Sabit sayıda elemana sahip Stream veya rastgele eleman içeren Streamlerde kullanılabilir.
/*----------------------------------------------------------------------------------------------------------------------
Stream arayüzünün generate metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.Random;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
Random r = new Random();
Stream<Integer> s = Stream.generate(() -> r.nextInt(101)).limit(10);
s.forEach(System.out::println);
}
}
/*----------------------------------------------------------------------------------------------------------------------
Sınıf Çalışması: Elimizde rasgele isimlerden oluşan bir dizi bulunsun.
Bu diziden rasgele isimler üretilip yeni bir Stream elde edilsin.
Elde ediklen buy stream i ekrana basan programı yazınız
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.Random;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
Random r = new Random();
String [] names = {"özgür", "burak", "yusuf", "oğuzhan", "çağatay", "furkan", "mehmet", "zekiye", "ilker", "cüneyt", "selman", "gurur", "cihan"};
Stream.generate(() -> names[r.nextInt(names.length)]).limit(5).forEach(System.out::println);
}
}
iterate Metodu
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
Bu metod verilen bir tohum değerine göre tekil bir işlemi yapan UnaryOperator<T>
isimli bir arayüzü kullanmaktadır.
/*----------------------------------------------------------------------------------------------------------------------
Stream arayüzünün iterate metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
Stream.iterate(2, val -> val * 2).limit(10).forEach(System.out::println);
}
}
Stream Arayüzünün of() metodu
static <T> Stream<T> of(T... values)
Bu metodu bir diziden yada sonlu değerden bir Stream elde etmek için kullanılmaktadır.
/*----------------------------------------------------------------------------------------------------------------------
Stream arayüzünün of metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
Stream.of(1, 2, 3, 4).forEach(System.out::println);
}
}
/*----------------------------------------------------------------------------------------------------------------------
Stream sınıfının of metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
Integer [] a = {1, 2, 3, 4, 5};
Stream.of(a).filter(val -> val % 2 == 0).forEach(System.out::println);
}
}
Sınıf Çalışması: Klavyeden bir n sayisi isteyiniz, n adet rastgele Card sınıfı türünden nesneyi bir diziye aktarınız. Bu dizi içerisinde numaralı olan kartları ekrana yazdıran programı yazınız.
/*----------------------------------------------------------------------------------------------------------------------
Sınıf Çalışması: Karıştırılmış bir deste içerisinde AS, PAPAZ, KIZ, VALE olmayan kartları
ekrana yazdıran programı Card sınıfını ve getShuffledDeck metodunu kullanarak yazınız
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.stream.Stream;
import org.csystem.games.cardgames.Card;
import org.csystem.games.cardgames.CardValue;
public class App {
public static void main(String[] args)
{
Card [] deck = Card.getShuffledDeck();
Stream.of(deck).limit(20)
.filter(c -> c.getValue() != CardValue.ACE && c.getValue() != CardValue.QUEEN && c.getValue() != CardValue.KING && c.getValue() != CardValue.KNAVE)
.forEach(System.out::println);
}
}
Aynı uygulama order kullanılarak aşağıdaki gibi yapılabilir. Burada vale kız, papaz ve as peşpeşe ve sonda gelmektedir.
/*----------------------------------------------------------------------------------------------------------------------
Yukarıdaki sınıf çalışmasının ordinal kullanılarak yapılmış hali
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.stream.Stream;
import org.csystem.games.cardgames.Card;
public class App {
public static void main(String[] args)
{
Card [] deck = Card.getShuffledDeck();
Stream.of(deck).limit(20)
.filter(c -> c.getValue().ordinal() < 9)
.forEach(System.out::println);
}
}
//CardSınıfı yapıştırılıcak.
StringBuilder & StringBuffer Sınıfı
Bu iki sınıf String sınıfına alternatif olarak kullanılmaktadır. Bu sınıflar String sınıfında olmayan özellikleri ve mutable olma özelliğini içermektedir. Bu iki sınıf aslında tamamen aynı sınıflardır, aralarında tek bir fark bulunmaktadır. StringBuffer
sınıfı Thread-Safe bir sınıftır. StringBuffer
sınıfı StringBuilder
sınıfının Thread güvenli olanıdır.
Programcı birden fazla thread ile aynı object'e bir sınıfa değişiklik yapılıyorsa tercih edilmelidir. Ancak tek threadli bir uygulamada yada aynı nesneye birden fazla threadin erişmeyeceği için tercih edilmemelidir.
Anahtar Notlar: String sınıfı değiştirilemez(immutable) olduğundan thread güvenlidir.
StringBuilder sınıfı adeta bir char türden bir dinamik büyüyen bir dizi gibi davranmaktadır.(Collection). StringBuilder
ve StringBuffer
adeta karakter açılımı türden bir Vector
gibi davranmaktadır.
StringBuilder/StringBuffer
sınıfının default constructor'ı 16 kapasite elemanlı boş bir karakter dizisi tutacak şekilde nesne yaratmaktadır. Sınıfın StringBuilder(int capacity) / StringBuffer(int capacity)
yapısındaki başlangıç metodu nesne yaratılırken kapasiteyi belirlemek için kullanılır.
StringBuilder/StringBuffer sınıfının String parametreli başlangıç metodu elimizde bir String referansı varsa ondan StringBuilder elde etmek için kullanılır.
StringBuilder sınıfı java.lang paketi içerisinde olduğundan doğrudan kullanılabilir. Sınıfın length ve capacity metotları ile içerisinde tutulan karakterin uzunluğu ve kapasitesi elde edilebilir.
örnek:
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder();
System.out.printf("Length=%d%n", sb.length());
System.out.printf("Capacity=%d%n", sb.capacity());
}
}
StringBuilder sınıfının toString
metodu içerisindeki karakterlerden oluşan bir String döndürür.
package org.csystem;
public class App {
public static void main(String[] args)
{
String s = "ankara";
StringBuilder sb = new StringBuilder(s);
System.out.printf("Length=%d%n", sb.length());
System.out.printf("Capacity=%d%n", sb.capacity());
}
}
StringBuilder sınıfının charAt
metodu ile belirli bir index'teki karakter elde edilebilir. setCharAt
metodu ile her hangi bir index'teki karakteri değiştirilebilir.
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
System.out.println(sb);
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
System.out.println(sb);
}
}
Sınıfın append()
metotlari ile varolan bir StringBuilder nesnesine istenilen tür için ekleme yapılabilir. Sınıfın belirli bir işlem yapan metotları fluent metoduna uygun olarak yazılmıştır. Böylelikle zincir çağırması şeklinde kullanılabilmektedir.
örn:
Sınıfın ```insert()``` metotları belirli bir indexten başlayarak araya ekleme yapmak için kullanılmaktadır.
```java
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("derece");
sb.insert(0, 30).insert(2, ' ');
System.out.println(sb);
}
}
Sınıfın reverse()
metodu, içerisindeki yazıyı terse çevirmek için kullanılmaktadır.
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
sb.reverse();
System.out.println(sb);
}
}
Sınıfın replace()
metodu ile belirli bir aralıktaki yazi değeri değiştirilebilir.
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının replace metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
sb.replace(0, sb.length(), "istanbul");
System.out.println(sb);
}
}
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının replace metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
sb.replace(0, 2, "istanbul");
System.out.println(sb);
}
}
Sınıfın substring()
metodu String sınıfındaki gibi kullanılabilir, benzer bir biçimde indexOf ve lastIndexOf
isimli metotlarda bu sınıfta bulunmaktadır. Sınıfın trimToSize
metodu capacity == length durumuna getirir.
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının trimToSize metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
System.out.printf("Capacity=%d%n", sb.capacity());
System.out.printf("Length=%d%n", sb.length());
sb.trimToSize();
System.out.printf("Capacity=%d%n", sb.capacity());
System.out.printf("Length=%d%n", sb.length());
}
}
Sınıfın deleteCharAt
metotları silme amaçlı kullanılmaktadır. deleteCharAt
metodu belirli bir indeksteki elemanı siler. delete
metodu ise belirli bir aralıktaki elemanları siler.
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının deleteCharAt metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
sb.deleteCharAt(0);
System.out.println(sb);
}
}
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının delete metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
sb.delete(0, 2); //[0, 2)
System.out.println(sb);
}
}
Sınıfın getChars()
metodu StringBuilder içerisinde belirli bir aralıkta bulunan karakterleri belirlenen bir diziye kopyalamakta kulllanılmaktadır. getChars
metodunun son parametresi kopyalanacak diziye ilişkin başlangıç ofset numarasını vermektedir. Burada kopyalanacak dizinin uzunluğunun kopyalanan karakter sayısına uygun olması programcının kendisine bırakılmıştır.
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının getChars metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
char [] dest = new char[sb.length()];
sb.getChars(0, sb.length(), dest, 0);
for (char ch : dest)
System.out.println(ch);
}
}
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının getChars metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("kara");
char [] dest = new char[sb.length() + 2];
dest[0] = 'a';
dest[1] = 'n';
sb.getChars(0, sb.length(), dest, 2);
for (char ch : dest)
System.out.println(ch);
}
}
setLength metodu var olan length'ten küçük girilirse length'i belirlenen boyuta çeker. Yani diğer karakterler kaybolur.
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının setLength metodu ile length değiştirilebilir. Boş olan yerler
'\0' (null character) ile doldurulur
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
System.out.printf("Length=%d%n", sb.length());
sb.setLength(20);
System.out.printf("Length=%d%n", sb.length());
for (int i = 0; i < sb.length(); ++i)
System.out.println(sb.charAt(i));
System.out.println("test");
}
}
/*----------------------------------------------------------------------------------------------------------------------
StringBuilder sınıfının setLength metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
public class App {
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("ankara");
System.out.printf("Length=%d%n", sb.length());
sb.setLength(3);
System.out.printf("Length=%d%n", sb.length());
for (int i = 0; i < sb.length(); ++i)
System.out.println(sb.charAt(i));
System.out.println("test");
}
}
Sınıf Çalışması: Klavyeden exit girilene kadar alınan yazıları bir String builder ile aralarında virgul olacak şekilde birleştiriniz.
package org.csystem;
import org.csystem.utils.Keyboard;
public class App {
public static void main(String[] args)
{
Keyboard kb = new Keyboard();
String s = null;
StringBuilder sb = new StringBuilder();
while (!(s = kb.getLine()).equals("exit")) {
if (sb.length() > 0)
sb.append(",");
sb.append(s);
}
System.out.println(sb);
}
}
Sınıf Çalışması: Klavyeden exit girilene kadar alınan yazıları bir liste tarzı collection sınıfına ekleyiniz. Bu sınıfın içerisindeki elemanları Stream API metotları kullanarak bir StringBuilder nesnesinde birleştiriniz.
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import org.csystem.utils.Keyboard;
public class App {
public static void main(String[] args)
{
Keyboard kb = new Keyboard();
List<String> list = new ArrayList<>();
String s;
while (!(s = kb.getLine()).equals("exit"))
list.add(s);
StringBuilder sb = new StringBuilder();
list.stream().forEach(str -> sb.append(str).append(" "));
System.out.println(sb);
}
}
Yukarıda da belirtildiği gibi programcı thread-safe bir sınıf kullanmak isterse, StringBuilder yerine StringBuffer
tercih etmesi daha uygundur.
Çünkü StringBuffer kullanırsa senkronizasyon işlemini kendisi yapmak zorundadır.
CharSequence Arayüzü
CharSequence arayüzü okunabilir karakter dizilimine ilişkin bir arayüzdür. StringBuilder, String, StringBuffer sınıfları bu arayüzü implements etmişlerdir. Bu arayüzün abstract metotları şunlardır;
char
charAt(int index)
int
length()
CharSequence
subSequence(int start, int end)
String
toString()
StringBuilder/StringBuffer sınıfının CharSequence parametreli bir başlangıç metodu da bulunmaktadır.
Optional<T> Sınıfı
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
Optional<T>
sınıfı içerisinde null yada null olmayan bir değeri tutabilmek için tasarlanmış, özel bir sınıftır. Java 8 ile birlikte eklenmiştir.
Optional sınıfının isPresent()
isimli metodu Optional içerisinde değer varsa -true yoksa -false değeri ile geri döner.
Bu sınıf özellikle kontrol amaçlı kullanılan bir sınıftır. Bu sınıfın mantığı şu şekildedir, "içerisinde değer vardır yada yoktur".
Örneğin Stream sınıfının bazı metotları, karar verme noktasında Optional<T>
referansı ile dönerler. Aşağıdaki örnekte max(Comparator<? super T> comparator)
metodu kullanılmaktadır.
/*----------------------------------------------------------------------------------------------------------------------
Optional<T> sınıfı
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(i);
Optional<Integer> result = list.stream().max((a, b) -> a - b);
if (result.isPresent())
System.out.println(result.get());
else
System.out.println("Stream boş");
}
}
Sınıf Çalışması: Product sınıfını kullanarak bir product listesi içerisinde en pahalı ve en ucuz ürünü bulan programı Stream API'leri kullanarak yazınız.
package org.csystem;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class App {
public static void main(String[] args)
{
List<Product> products = new ArrayList<>();
products.add(new Product("123", "meyve suyu", 10.5, 3, LocalDate.of(2016, 3, 20), 50));
products.add(new Product("1233", "muz", 5.5, 1, LocalDate.of(2016, 2, 22), 20));
products.add(new Product("1234", "ton balığı", 20.0, 10, LocalDate.of(2016, 5, 22), 100));
products.add(new Product("1235", "Barbunya", 7.5, 2, LocalDate.of(2016, 6, 24), 70));
Optional<Product> minProduct = products.stream().max(
(p1, p2) -> Double.compare(p2.getPrice(), p1.getPrice()));
Optional<Product> maxProduct = products.stream().max(
(p1, p2) -> Double.compare(p1.getPrice(), p2.getPrice()));
if (minProduct.isPresent())
System.out.printf("Min:%s%n", minProduct.get());
else
System.out.println("Ürün listesi boş");
if (maxProduct.isPresent())
System.out.printf("Max:%s%n", maxProduct.get());
else
System.out.println("Ürün listesi boş");
}
}
Sınıf Çalışması: Bir ürün listesi oluşturunuz. Sırasıyla fiyat aralığı, isim ve son kullanma tarihine göre seçimlerden oluşan basit bir menu programını yazınız
package org.csystem;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.csystem.utils.Keyboard;
public class App {
public static void main(String[] args)
{
ProductApp app = new ProductApp();
app.run();
}
}
class ProductApp {
private static List<Product> m_products;
private Keyboard m_kb;
static {
m_products = new ArrayList<>();
m_products.add(new Product("123", "meyve suyu", 10.5, 3, LocalDate.of(2016, 3, 20), 50));
m_products.add(new Product("1233", "muz", 5.5, 1, LocalDate.of(2016, 2, 22), 20));
m_products.add(new Product("1234", "ton balığı", 20.0, 10, LocalDate.of(2016, 5, 22), 100));
m_products.add(new Product("123478", "muzlu süt", 4.0, 10, LocalDate.of(2016, 5, 22), 100));
m_products.add(new Product("1235", "Barbunya", 7.5, 2, LocalDate.of(2016, 6, 24), 70));
}
private static void displayMenu()
{
System.out.println("1.Fiyat");
System.out.println("2.İsim");
System.out.println("3.Son kullanma Tarihi");
System.out.println("4.Çıkış");
System.out.print("Seçenek:");
}
private void listByPrice()
{
double minPrice = m_kb.getDouble("Minimum fiyat");
double maxPrice = m_kb.getDouble("Maximum fiyat");
if (minPrice > maxPrice) {
System.out.println("Geçersiz fiyat aralığı");
return;
}
m_products.stream().filter(p -> p.getPrice() >= minPrice && p.getPrice() <= maxPrice).forEach(System.out::println);
}
private void listByName()
{
String name = m_kb.getLine("İsim giriniz");
m_products.stream().filter(p -> p.getName().contains(name)).forEach(System.out::println);
}
private void listByExpiryDate()
{
try {
LocalDate expiryDate = LocalDate.parse(m_kb.getLine("Tarihi giriniz"));
m_products.stream().filter(p -> p.getExpiryDate().isAfter(expiryDate)).forEach(System.out::println);
}
catch (Exception ex) {
System.out.println("Geçersiz tarih formatı");
}
}
public ProductApp()
{
m_kb = new Keyboard();
}
public void run()
{
EXIT_MENU:
for(;;) {
displayMenu();
int option = m_kb.getInt();
if (option < 0 || option > 4) {
System.out.println("Geçersiz seçenek");
continue;
}
switch (option) {
case 1:
this.listByPrice();
break;
case 2:
this.listByName();
break;
case 3:
this.listByExpiryDate();
break;
default:
break EXIT_MENU;
}
}
}
}
Stream<T> Arayüzünün Skip Metodu
java Stream<T> skip(long n)
Bu metot parametresi ile aldığı n kadar elemanı atlayarak Stream olarak vermektedir.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> sınıfının skip metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(i + 1);
list.stream().skip(3).forEach(System.out::println);
}
}
Stream Arayüzünün sorted() Metotları
sorted()
sorted(Comparator<? super T> comparator)
Bu metotlar bir Collection yada bir Stream içerisindeki değerleri sıralı bir Stream halinde verirler. sorted()
metodunun parametresiz versiyonu doğal bir sıralama yapar, Comparator arayüz referans parametreli versiyonu ise klasik olarak belirlenen kritere göre sıralama yapar.
sorted()
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class App {
public static void main(String[] args)
{
Random r = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(r.nextInt(101));
list.stream().forEach(System.out::println);
System.out.println("*******************");
list.stream().sorted().forEach(System.out::println);
}
}
sorted(Comparator<? super T> comparator)
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class App {
public static void main(String[] args)
{
Random r = new Random();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(r.nextInt(101));
list.stream().forEach(System.out::println);
System.out.println("*******************");
list.stream().sorted((a, b) -> b - a).forEach(System.out::println);
}
}
Stream Arayüzünün findFirst()
& findAny()
Metodu
Bu metotlar Stream içerisinde herhangi bir eleman var mı?, yada Stream içerisinde ilk eleman var mı? şeklinde bir bilgi verir. Bu bilgiyi Optional<T>
referansı türünden döndürür, programcı bunu kontrol edip testi yapabilir.
findAny()
metodu, aslında Stream boş ise boş veya dolu mu kontrolunu yapmak içinde kullanılır.
Bu metotlar liste tarzı Collectionlarda aynı etkiye sahiptir fakat başka Collectionlarda değişebilir.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün findAny metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(i + 1);
if (list.stream().findAny().isPresent())
System.out.println("Liste dolu");
else
System.out.println("Liste boş");
}
}
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün findFirst metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
public class App {
public static void main(String[] args)
{
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; ++i)
list.add(i + 1);
if (list.stream().findFirst().isPresent())
System.out.println("Liste dolu");
else
System.out.println("Liste boş");
}
}
Stream<T>
Arayüzünün static concat()
Metodu
static <T> Stream<T> concat(Stream<? extends T> a,
Stream<? extends T> b)
Bu metot iki tane Stream'in birleşiminden oluşan bir Stream referansı döndürür.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün concat metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
String [] names1 = {"Batu", "Hakan", "Gülay", "Buse"};
String [] names2 = {"Ali", "Veli", "Selami"};
Stream.concat(Stream.of(names1), Stream.of(names2))
.filter(s -> s.contains("a"))
.forEach(System.out::println);
}
}
Bu metot ile birbirinden farklı türden Collectionlarda Stream üzerinde birleştirilebilir.
/*----------------------------------------------------------------------------------------------------------------------
Stream<T> arayüzünün concat metodu
----------------------------------------------------------------------------------------------------------------------*/
package org.csystem;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class App {
public static void main(String[] args)
{
String [] names1 = {"Batu", "Hakan", "Gülay", "Buse"};
List<String> names2= new ArrayList<>();
names2.add("Ali");
names2.add("Veli");
names2.add("Selami");
Stream.concat(Stream.of(names1), names2.stream())
.filter(s -> s.contains("a"))
.forEach(System.out::println);
}
}
Stream<T>
Arayünden Collection Elde Edilmesi
Bunun için tipik olarak collect() isimli metot kullanılmaktadır. collect() metodu Collector<T, A, R>
isimli generic bir arayüz referansı almaktadır.