Aşağıdaki kod parçasında sadece 1 karakteri değiştirerek, işlem süresini yaklaşık 5’te 1’ine indirebileceğimizi söylesem ne düşünürsünüz?
long t = System.currentTimeMillis(); Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println("toplam:" + sum); System.out.println("işlem süresi: " + (System.currentTimeMillis() - t) + " ms") ;
Çıktı:
toplam:2305843005992468481
işlem süresi: 6756 ms
|
Yukarıdaki kod parçası hakkında biraz düşündükten sonra, aşağıdaki daha hızlı çalışan kod parçasını inceleyebilirsiniz.
long t = System.currentTimeMillis(); //Long sum = 0L; long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println("toplam:" + sum); System.out.println("işlem süresi: " + (System.currentTimeMillis() - t) + " ms") ;
Çıktı:
toplam:2305843005992468481
işlem
süresi: 1248 ms
Yukarıdaki hız farkının, Java 1.5 ile hayatımıza giren “Autoboxing”
özelliğinin dikkatsiz kullanımından kaynaklandığını söyleyebiliriz.
Farkın nedenine devam etmeden, öncelikle Java’da “Autoboxing”
ve “Unboxing” kavramını açıklamaya çalışalım.
Java’da tipler primitive ve referans olmak üzere ikiye
ayrılmaktadır. Java’da 8 adet primitive tip bulunmaktadır. Her primitive tipe
karşılık gelen de bir referans tipi(wrapper class) vardır.
Primitive tipler
|
Referans Tipler(Wrapper Class)
|
boolean
|
Boolean
|
byte
|
Byte
|
char
|
Character
|
float
|
Float
|
int
|
Integer
|
long
|
Long
|
short
|
Short
|
double
|
Double
|
Aşağıdaki örnek kod parçasında autoboxing ve unboxing kavramlarına birer örnek görebilirsiniz. Burada Long bekleyen bir ArrayList’e long bir değer eklenmektedir. Java 1.4’te bu işlemin yapılabilmesi için primitive değerin uygun bir referans tip içine eklenerek(boxing) yapılması gerekirdi. Java 1.5 itibariyle bu işlemi compiler bizim için yapmaktadır. Böylece fazladan kod yazmak zorunda kalmıyoruz.
Yani aşağıdaki kod;
List<Long> longList = new ArrayList<>(); long i = 4; longList.add( i ); //autoboxing long j = longList.get( 0 ); //unboxing
compiler tarafından otomatik olarak aşağıdaki koda çevrilmektedir.
List<Long> longList = new ArrayList<>(); long i = 4; longList.add(Long.valueOf( i ) ); long j = longList.get( 0 ).longValue();
Buradan ilk kodumuzun da aslında aşağıdaki gibi bir koda çevrildiğini söyleyebiliriz. Bu işlemin uzun sürmesinin nedenini de kod çalışırken, 2147483647 adet gereksiz Long instance’ı oluşturmaya çalışması olarak açıklayabiliriz.
long t = System.currentTimeMillis(); Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += new Long(i); } System.out.println("toplam:" + sum); System.out.println("işlem süresi: " + (System.currentTimeMillis() - t) + " ms") ;
Çıktı:
toplam:2305843005992468481
işlem
süresi: 6764 ms
Sonuç olarak, daha hızlı çalışacak Java kodları yazmak için, autoboxing ve unboxing durumlarını dikkate almalıyız. Gereksiz instance oluşturma işlemlerinden kaçınmalı, hesap gerektiren çoklu işlemlerde primitive tipleri tercih etmeliyiz diyebiliriz.
Yararlandığım Kaynaklar
Autoboxingand UnboxingAutoboxing
ali kemal taşçı