Ahmet Orsorlu
ABOUT THE AUTHOR

Ahmet Orsorlu

Matematik Mühendisliği lisans, Bilgisayar Mühendisliği yüksek lisans mezunu. Halen Logo Business Solutions'ta Yazılım Uzmanı olarak görev yapmakta. Basit ve temiz olan herşeyi seviyor. Galatasaraylı. Stephen King ve Metallica aşığı.

Java Makale #1 – String, StringBuffer, StringBuilder

Java kodlaması yaparken hemen hepimiz string işlemleri için String sınıfını kullanırız. Çünkü kullanımı basittir ve ekstradan bilgi ihtiyacı gerektirmez. Peki ya performans? Bu kullanım kolaylığı bize performans olarak nasıl yansıyor? Gelin şimdi String sınıfının avantaj ve dezavantajlarından bahsederek, yerine hangi durumlarda hangi sınıfları kullanabileceğimize göz atalım.

String Sınıfı

Öncelikle nasıl kullanıyoruz ona bir göz atalım.

String myString = "This is a literal string";

Şöyle kullanımı da mevcut;

String myString2 = new String("This is another literal string");

ancak fazladan bir nesne yaratmış oluyoruz. Yani, bu kullanımın

String myString3 = new String(myString);

bundan bir farkı yok. Yani fazladan bir nesne oluşmuş oluyor. Java String sınıfına zaten özel olarak davranarak, ilk örnekteki gibi oluşmasını sağlıyor.

Asıl konumuza dönersek, Java dilinde String sınıfı özel bir sınıf. Sadece okunabilir formda oluşturuluyor (ki bu nesnelere immutable nesneler deniyor. İngilizce kaynak için : Immutable Objects). Yani bir kere oluşturulduktan sonra oluşturulan nesne değiştirilemiyor. Hemen bir örnekle açıklayalım:

String firstString = "first";
String secondString = "second";
String thirdString = firstString.concat(secondString);
System.out.println("1." + firstString);
System.out.println("2." + thirdString);

Kod parçasının ekran çıktısı ise;

1.first
2.firstsecond

şeklinde oluyor. concat metodu iki String nesnesinin birleştirilmesini sağlıyor (+ işlemi de aynı işi yapıyor). 3. satırda olması beklenen firstString nesnesinin değişmesi. Ancak çıktının ilk satırdan görüldüğü üzere firstString nesnesi aynen kalmış, tamamen yeni nesne oluşturulmuş. String nesnesi bir kere yaratıldıktan sonra artık değiştirilemez (immutable) hale geliyor. Görüldüğü üzere her yeni String nesnesi birleştirilmesi sırasında tamamen yeni bir String nesnesi oluşuyor. Sadece birleştirme değil, String sınıfı üzerindeki tüm düzenleme işlemlerinde yeni bir nesne oluşuyor.

Peki neden immutable nesneler var? Birincisi, işlerin basit olmasını sağlıyor. İkincisi, verimizin değiştirilemez kalmasını sağlıyor. Bunu bir örnekle açıklayacak olursak;

public class Person {

	String name;
	Date birthday;

	public Person(String name, Date birthday) {
		this.name = name;
		this.birthday = birthday;
	}

	public String getName() {
		return name;
	}

	public Date getBirthday() {
		return birthday;
	}
}

Basit bir Person sınıfı. Kişinin ismini (name) ve doğum tarihini (birthday) tutuyor.

Person ali = new Person("ali", new Date(2000, 1, 1));
String name = ali.getName();
name.concat("veli");
Date birthday = ali.getBirthday();
birthday.setYear(2023);

System.out.println("Name: " + ali.getName());
System.out.println("Birth year: " + ali.getBirthday().getYear());

Öncelikle bir Person nesnesi yaratıyoruz. Daha sonra Person sınıfının getName metoduyla ismi alıyoruz ve 3. satırda “veli” stringini ekliyoruz. Daha sonra getBirthday metoduyla doğum tarihini alıyoruz ve yılını 2023 olarak değiştiriyoruz. Kod parçasının ekran çıktısına baktığımızda;

Name: ali
Birth year: 2023

Gördüğümüz üzere immutable nesne olan name değiştirilemezken, birthday nesnesi dışardan istenildiği gibi değiştirilebildi. birthday nesnesinin de değiştirilememesini istiyorsak ekstradan bir işlem yapmamız gerekiyor. Bu konuya ayrı bir yazıda değiniriz. Burada önemli olan bunun için immutable nesnelerde ekstra bir çaba sarfetme gereksinimimizin olmaması.

Peki yoğun düzenleme işlemleri olduğunda bir sürü geçici nesne oluşmasını önlemenin yolu nedir? Yani, String sınıfının alternatifleri nelerdir? Bu noktada imdada iki sınıf yetişiyor; StringBuffer ve StringBuilder.

StringBuffer ve StringBuilder Sınıfları

Aslında bu iki sınıf sadece bir durum dışında aynı amaca hizmet ediyorlar. Hemen hemen aynı sınıflar yani (hatta sanırım tüm metotları aynı). Tek farkları, StringBuffer synchronized olarak çalışırken, StringBuilder bunun garantisini vermiyor. Bu konuya en son değinelim.

StringBuffer sınıfı String sınıfının varlığından beri var (JDK 1.0’dan beri). Amacı, immutable String sınıfının yukarıda bahsettiğimiz dezavantajlarını giderecek mutable sınıf olması. Yani, düzenleme işlemi sonucunda düzenlenen nesne de değişmiş oluyor. Hemen bir örnekle açıklayalım;

StringBuffer strBuffer = new StringBuffer("This is a StringBuffer object");
StringBuffer strBuffer2 = strBuffer.append(" and now modified.");

System.out.println("1." + strBuffer);
System.out.println("2." + strBuffer2);

ve kodun ekran çıktısı;

1.This is a StringBuffer object and now modified.
2.This is a StringBuffer object and now modified.

Görüldüğü üzere, append metodu sonucu strBuffer nesnesi de değişmiş oldu. Yoğun string işlemlerinde oldukça faydalı bir sınıf. StringBuffer nesnesini String nesnesine çevirmek de gayet kolay; toString metodu.

StringBuffer sınıfı yazılırken, multithread uygulamalar da düşünülerek synchronized (link: threadler hakkında Türkçe güzel bir makale) olarak yazılmış. Yani, multithread uygulamalarda bir thread bir StringBuffer nesnesi üzerinde değişiklik yaparken veya okurken diğer bir thread o StringBuffer nesnesine erişemiyor. StringBuffer sınıfı size synchronized olma garantisini veriyor.

Ancak, synchronized işlemi oldukça büyük bir masraf getiriyor. Eğer böyle bir duruma ihtiyacınız yoksa (genellikle single thread uygulamalarda böyle bir ihtiyaç yoktur) sizin için çok da kullanışlı bir sınıf olmayabilir. Bu durumu göz önünde bulunduran StringBuilder sınıfı JDK 1.5 ile hayatımıza girmiş durumda. Daha önce de belirttiğim gibi, StringBuffer sınıfından tek farkı synchronized olarak çalışmaması. Yani, düzenleme işlemlerinde StringBuffer sınıfından daha hızlı. Ancak, multithread uygulamalarda StringBuffer sınıfı kadar güvenli değil.

Adet yerini bulsun ve bu sınıfla ilgili de örnek yazalım;

StringBuilder strBuilder = new StringBuilder("This is a StringBuilder object");
StringBuilder strBuilder2 = strBuilder.append(" and now modified.");

System.out.println("1." + strBuilder);
System.out.println("2." + strBuilder2);

ve ekran çıktısı;

1.This is a StringBuilder object and now modified.
2.This is a StringBuilder object and now modified.

Örnek bir önceki örnekle tamamen aynı.

Son olarak konunun özeti olarak güzel bir reçete verelim 🙂 :

string işlemlerinde;

  • Düzenleme işlemleri çok kullanılmayacak, daha çok okuma işlemi yapılacaksa String sınıfını
  • Düzenleme işlemleri sıklıkla yapılıyor ve multithread çalışılıyorsa StringBuffer sınıfını
  • Tüm diğer durumlarda StringBuilder sınıfını

kullanabilirsiniz.

Oldukça basit bir reçete oldu değil mi? 🙂

Java İpucu #1 – String Nesnesinde Nümerik Karakter Kontrolü

Bir string nesnesinin tamamen nümerik karakterlerden (0-9) oluştup oluşmadığının kontrolü kimi zaman ihtiyaç dahilinde olabilir. Örneğin, herhangi bir ürünün kodu veritabanında text olarak tutulabilir ve bu kodun tamamının nümerik karakterlerden oluşması istenebilir. Bir string nesnesinin nümerik karakterlerden oluşup oluşmadığı çeşitli yöntemlerle kontrol edilebilir:

İlk yöntem, Integer sınıfının parseInt metodunu kullanmak. Basit bir örnekle görelim:

public static boolean stringNumericTest1(String code) {
	try {
		Integer.parseInt(code);
	} catch (NumberFormatException numberFormatException) {
		return false;
	}
	return true;
}

Burada tek yaptığımız şey parseInt metodunu kullanarak, fırlatabileceği NumberFormatException nesnesini yakalamak. Yani, tüm işi parseInt metodu hallediyor. Eğer, metot string nesnesini int tipine çeviremez ise NumberFormatException nesnesi fırlatıyor. Güzel yanı, kullanımının sade ve basit olması. Burada dikkat edilmesi gereken nokta parseInt metodu başında “-“ karakteri olan stringleri de çevirebiliyor. Eğer bu durum sizin için uygun değilse, metottan dönen int değerinin negatif olup olmadığını kontrol edebilirsiniz.

İkinci yöntem biraz daha alt seviye bir işlem. Tüm karakter kontrolleri elle yapılıyor:

public static boolean stringNumericTest2(String code) {
	for (int i = 0; i < code.length(); i++) {
		if(!Character.isDigit(code.charAt(i)))
			return false;
	}
	return true;
}

Görüldüğü üzere, string nesnesinin tüm karakterleri sırayla dolaşılıyor ve Character sınıfının static metodu isDigit ile o karakterin nümerik olup olmadığını bakılıyor. Nümerik olmayan karakterle karşılaşıldığı anda metot false değerini döndürüyor. Tüm karakterler nümerik ise metot true değerini döndürüyor.

Üçüncü ve son yöntem ise düzenli ifadeler (regular expressions) yöntemi:

public static boolean stringNumericTest3(String code) {
	if(code.matches("[0-9]+"))
		return true;
	return false;
}

String sınıfının matches metoduna istenilen düzene sahip düzenli ifade verilerek string nesnesinin bu düzenli ifadeye uyup uymadığının kontrolü yapılıyor. Belirtilen düzenli ifade ([0-9]+) tam anlamıyla konuyu içeriyor 🙂 : “code nesnesi 1 veya daha fazla nümerik karakterden mi oluşuyor?”. Kullanımı gayet basit bir yöntem daha. Bu yöntemin güzelliği düzenli ifadeyi değiştirerek string nesnesinin istenilen şekilde kontrolü mümkün olabiliyor. Örneğin, bilimsel notasyondaki sayılar (5e+10 gibi) bile kontrol edilebilir hale getirilebilir. Düzenli ifade bilgisi gerektiğini söylememe gerek yok herhalde 🙂

Şimdilik bu kadar. Umarım faydalı olabilecek bir konu olmuştur. Herkese iyi çalışmalar.

Faydalı Uygulamalar #2 – TeraCopy

Windows işletim sistemlerinde (tümünde) Windows Explorer’ın (Windows işletim sisteminin dosya yöneticisi) kes/kopyala/yapıştır işlevselliğinden (!) sanırım herkes muzdariptir. Onlarca dosya kesilir/kopyalanır, ilgili yere yapıştırılır. Tam ortadaki dosya kopyalanırken sorun oluşur ve devam edilemez duruma gelinir. Windows Explorer hatanın oluştuğu dosyadan itibaren kopyalama işlemini durdurur. Hangi dosyalar kopyalanmış, hata oluşan dosyadan sonra geriye hangi dosyalar kopyalanmadan kalmıştır? Tam bir başbelası durum.

TeraCopy, Windows Explorer’ın kes/kopyala/yapıştır fonksiyonlarını ele geçiren (!) basit ama çok kullanışlı bir uygulama. Programı yükledikten sonra sizin ekstradan herhangi birşey yapmanıza gerek kalmıyor. Her kes/kopyala/yapıştır işleminizde TeraCopy otomatik olarak çalışıyor.

Şimdi gelelim programın özelliklerine. Öncelikle işlemler çok hızlı (en azından öyle iddaa ediyorlar. Tamam bence de öyle 🙂 ). Kopyalama işlemini istediğimiz zaman durdurup daha sonra kaldığımız yerden devam ettirebiliyoruz. Kopyalanırken hata oluşan dosyaları listeden görerek tekrar kopyalanmasını sağlayabiliyoruz. Tüm işlemler anında listede gözüküyor, bu sayede hangi dosyaların kopyalandığını, hangilerinde hata oluştuğunu rahatlıkla görebiliyoruz.

Üstelik uygulama bireysel kullanım için ücretsiz. Pro versiyonunun özellikleri de çok cazip gelmedi açıkçası.

Son söz; Windows yüklendikten sonra kurulması gereken ilk programlardan. Henüz kurmadıysanız hemen edinin ve kurun.

TeraCopy sayfası

TeraCopy indirme linki

Faydalı Uygulamalar #1 – Wunderlist

Çoğu zaman aklımıza gelenleri, yapmayı düşündüklerimizi veya yapmamız gerekenleri aklımıza not edebileceğimizi düşünür ve kimi zaman (kendimizi kandırmayalım, çoğu zaman) bir kısmını unuturuz. İşte bir görev yöneticisi / sanal not defteri olan Wunderlist tam bu noktada devreye giriyor (Hayır, unutkanlık gidermiyor (: ).

 

Wunderlist, ev ödevlerinizi, doğum günü tarihlerini, alışveriş listelerinizi, iş görevlerinizi tutabileceğiniz sanal bir not defteri. Üstelik tamamen ücretsiz ve kullanımı oldukça kolay. Hemen tüm platformlarda (iPhone, iPad, Android, Windows, Mac ve web üzerinden) çalışabiliyor. Windows üzerinde kurduktan hemen sonra basit birkaç adımda girdiğim görevleri birkaç saniye içerisinde android telefonumdaki uygulamamda da görebildim. Uygulamanın geliştiricileri tamamen kullanım kolaylığı gözetmişler. Gereksiz hiçbir ayrıntı gözüme çarpmadı Wunderlist’te. Bunun yanında konu ile ilgili gerekli hemen tüm ihtiyaçlara sahip. Ayrıca dileğimiz notları ve görevleri arkadaşlarımızla paylaşabilmemizi sağlayan paylaşma özelliği de eklenmiş.

Wunderlist’i web üzerinden hemen kullanmaya başlamak için sizi buraya alalım…