Java ile 24 kahve molası


Bölüm 3: Diziler ( 26.03.2004 )



Yüklə 0,89 Mb.
səhifə9/23
tarix07.01.2022
ölçüsü0,89 Mb.
#80528
1   ...   5   6   7   8   9   10   11   12   ...   23

Bölüm 3: Diziler ( 26.03.2004 )


Şuanda sabahın saat 3 buçuğu. Yeni hazırladığım sıcak kahvemi yudumlarken, Java ile ilgilenmekten saatin ne kadar geç olduğunun farkına bile varamadım. Geçen hafta boyunca, Java programlama dilinin temellerini incelemeye devam ettim. Doğruyu söylemek gerekirse, sıkıcı olan bir kaç konu inceledim. Bunlardan birisi dizilerdi.

Hemen her programlama dilinde olduğu gibi dizilerinde java'da sıkıcı bir yeri var. Sıkıcı olmasını nedeni belki de, veri saklama ile ilgili olarak günümüz teknolojilerinin getirdiği veri tabanı, xml, gelişmiş koleksiyonlar gibi kavramların çok daha fazla tercih ediliyor olması. Ancak ne olursa olsun, hangi programlama dili olursa olsun ve kavramları ne kadar sıkıcı olursa olsun, bunları bilmekte, incelemekte fayda var. Bu sabah saatlerindeki kahve molamda, dizilerin Java programlama dili içindeki yerini incelemeye çalışacağım. Bir diziyi belki de en güzel şu şekilde tanımlayabiliriz.



Dizi, belli bir sayıda ve aynı veri türünden değişkenlere, aynı isim altında erişilmesini sağlayan bir referanstır.

Aslında bu tanım içerisinde çok geniş kavramlar var ve açıklanması gerekli. Her şeyden önce, dizilerin referans olduklarını söylüyor. Java dilinde de, C#'ta olduğu gibi diziler referans tipli verilerdir. Dolayısıyla bir dizi, belleğin yığın (stack) kısmında tutulurken, dizi elemanlarının tamamı, öbek (heap)'te yer alır. Yani dizinin adı, öbekteki elemanların başlangıç adresine işaret eder. Bu dizilerin en önemli unsurlarından birisidir.

Diğer yandan, diziler aynı veri türünden elemanlara sahip olmalıdır. Bununla birlikte dizilerin eleman sayısı da oluşturulurken belirlenir. Dolayısıyla, bir diziyi en baştan boyutlandırdığımızda, belirtilen sayıda elemanı aktarabiliriz ve buda dizinin boyutu ile dinamik olarak oynamamızı engeller. Doğruyu söylemek gerekirse bu kısıtlamalar belki de C# dilinde koleksiyonları geliştirilmesine ve daha çok önem kazanmasına neden olmuştur. Kim bilir belki Java dilinde ‘de koleksiyonlar var. Şimdilik karşıma çıkmadılar.

O halde işe referans veri tipi olan dizilerin nasıl tanımlanacağından başlamak gerekiyor. Referans tipli olması, dizilerin oluşturulurken new yapılandırıcı kullanılarak oluşturulması gerektiği sonucunu ortaya çıkartıyor. Nitekim, diziler referans tipli nesnelerdir. Dolayısıyla bir sınıf örneği olmak zorundalar. Ancak diğer yandan, bir diziyi oluştururken new yapılandırıcısını kullanmak zorunda değiliz. Dizi elemanlarına, 0 tabanlı bir indis sistemi ile erişebilmekteyiz. Bu anlamda dizilerin, döngüler ile kardeş olmalarını gayet iyi anlayabiliyorum. Şimdi dizi kavramını incelemek için basit ama hızlı bir örnek geliştirmek düşüncesindeyim. Kahvemden bir yudum alıyorum ve aşağıdaki örneği yazıyorum. 

public class Dizi
{
    public static void main(String[] args)
    {
        int dizi1[]=new int[10];
        for(int i=0;i        {
            dizi1[i]=i*2;
            System.out.println((i+1)+". eleman="+dizi1[i]);
        }
    }
}

Uygulamayı başarı ile derledikten sonra çalıştırdığımda aşağıdaki sonucu aldım.

Kodların çalışma sistematiği oldukça basit. Diziyi tanımlamak için new yapılandırıcısını kullandık ve dizinin integer veri tipinden 10 elemanlı olmasını sağladık. Bu noktadan sonra dizimize elemanlar atamak için bir döngü kullandık. Bu döngü dizimizin boyutuna kadar hareket eden ve her bir elemana indis değerinin iki katını aktaran bir yapıda. Kullandığımız length özelliği, dizilerin boyutunu elde etmekte kullanılmakta. Buradan da zaten, dizilerin bir Java sınıfına ait olduğu sonucuna varabiliriz. Kodumuzda, dizi elemanlarını okumak içinde aynı döngü içindeki dizi1[i] şeklindeki yazımı kullandık. Dizileri yukarıdaki örnekte olduğu gibi new yapılandırıcısı ile tanımlayabileceğimiz gibi, başka alternatif bir yol da kullanabiliriz. Benzer bir örnek uygulama aşağıda yer alıyor.



public class Dizi2
{
    public static void main(String[] args)
    {
        int[] dizi={1,3,5,7,9,11,13,15}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
    }
}

Burada diziyi tanımlarken elemanlarını da baştan atamış olduk. Bu aynı zamanda verdiğimiz eleman sayısına göre dizinin otomatik olarak boyutlandırıldığını da göstermektedir. Son örneğimizin bellekteki yerleşim planına göz atarsak aşağıdaki tasvire benzer bir yapının oluştuğunu görürüz.



Peki ya bir diziye tanımlandığı veri tipinden başka bir tipte eleman eklemeye kalkarsak ne gibi sonuçlarla karşılaşabiliriz. Doğrusu bunu merak ediyorum. Bu nedenle yukarıdaki örnekte, integer tipteki dizimize, başka bir veri tipinden eleman eklemeye karar verdim. Bu amaçla, 'a' karakterini sincice dizi elemanları arasına yerleştirdim.



public class Dizi2
{
    public static void main(String[] args)
    {
        int[] dizi={1,3,5,7,9,11,'a',15}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
    }
}

Uygulamayı derlediğimde her hangi bir hata mesajı ile karşılaşmadım. Diğer yandan uygulamayı çalıştırdığımda aşağıdaki hata mesajı beni bekliyordu.

Vouv! Hiç beklemediğim bir durum. 7nci eleman yani 'a' değerinin karakter karşılığı oluvermişti bir anda. Hım. Aslında bu istemediğim bir sonuç. Ben daha çok bir hata mesajı bekliyordum. Yoksa dizi tanımında bir tanımlama hatası mı yaptım? Denemeye devam etmeye karar verdim. Sabahın kaçı olursa olsun ben bu hata mesajını bulacaktım. Kodları aşağıdaki şekilde değiştirdim. Aklıma ilk gelen integer değilse bir double değeri buraya koymak oldu. Hatta bir tane değil bir kaç farklı veri tipinden değerler koymak.



public class Dizi2
{
    public static void main(String[] args)
    { 
        int[] dizi={1,"Selam naber",5,true,9,11,15.154654,15}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        } 
    }
}

Sonunda başardım. İstediğim hata mesajlarını aldım ve dizi tanımına sadık kaldım.

Ancak dizileri kullanırken başıma gelebilecek diğer hataları da incelemek istiyorum. Öncelikle dizide olmayan bir indis elemanı oluşturmak istersem veya ona ulaşmak istersem ne olur? Fazla söze gerek yok hemen kodları yazmak lazım. Bu kez 5 elemanlı bir diziye 6ncı elemanı eklemeye çalışacağım.



public class Dizi2
{
    public static void main(String[] args)
    { 
        int[] dizi={1,2,3,4,5}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        dizi[6]=7; 
    }
}

Uygulama yine hatası olarak derlendi. Umarım bu sefer çalıştırdığımda istediğim hatayı alabilirim. Evet. Mükemmel. Hatayı elde etmeyi başardım.

Dizileri tanımlarken, aynı veri türünden elemanları grupladığımızdan bahsetmiştik. Farklı bir durum daha vardır. Bu da bir diziyi Java dilinin en üst sınıf olan (C# taki gibi) Object türünden tanımlamak ve elemanları birer nesne olarak belirlemektir. Bu teknikte, dizinin tüm elemanları birer nesnedir. Bu anlamda bellekteki dizilişte farklı olmaktadır. Öyle ki, Object türünden bir dizi tanıladığımızda, dizinin elemanları öbekte tutulurken her bir eleman nesne olduğu için, yine öbekteki asıl alanlarına referans eden değerleri taşırlar. Ancak dizi elemanlarına eriştiğimizde, bu nesnelerin referans ettikleri öbek alanlarındaki verilere ulaşılır. Hemen bununla ilgili bir örnek yapmakta fayda var.



public class DiziObject
{
    public static void main(String[] args)
    { 
        Integer eleman1=new Integer(456);
        String eleman2=new String("Ben bir stringim...");
        Double eleman3=new Double(45.45687);
        Boolean eleman4=new Boolean(true);

        Object[] dizi={eleman1,eleman2,eleman3,eleman4}; 


        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        } 
    }
}

Burada yaptığım Object türünden dizim için, new yapılandırıcılarını kullanarak sırasıyla integer, string, double ve boolean veri türlerinden birer nesne yaratmak ve daha sonra bu nesneleri Object türünden diziye aktarmak. Uygulama başarılı bir şekilde derlenecektir ve çalışacaktır.

Bu tekniğin bellekteki görünümü ise aşağıdaki tasvire benzer şekilde olacaktır.



Tabi burada aynı örneği aşağıdaki şekilde geliştirmeyi de düşündüm ama bu durumda hata mesajları ile karşılaştım. Çünkü aşağıdaki tekniği uygulayarak bir Object dizisi oluşturmaya çalıştığımda, elemanların her biri birer değişken olarak algılandı ve Object dizisine eklenmeye çalışılmak istendi. Ancak Object türünden bir dizi, kendisi gibi nesne elemanlarını kabul edeceğinden temel veri türlerinden tanımlanmış değişkenleri kabul etmedi ve derleyici bir sürü hata mesajı verdi.



public class DiziObject
{
    public static void main(String[] args)
    { 
        Object[] dizi={456,"Ben bir stringim",45.45687,true}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        } 
    }
}

Ancak burada dikkat etmemiz gereken bir nokta var. O da, String tipteki "Ben bir stringim" için bir hata mesajı almamış olmamız. Bunun nedeni aslında çok açık. Nitekim String veri türü, bir referans türüdür. Dolayısıyla new yapılandırıcısı ile bir String nesnesi yaratabiliriz. Bununla birlikte new yapılandırıcısın kullanmadan yukarıdaki gibi bir string tanımlamakta yine aynı işlevi gerçekleştirecektir. Sanırım burada bir dip not olarak şu iki ifadenin eşit olduklarını söyleyebiliriz.



String s=new String("Merhabar");

String s="Merhaba";

Gelelim diziler ile ilgili ne tür işlevleri gerçekleştirebileceğimize. Dizilerin Java'nın bir sınıfı olduğu söylemiştik. Evet, diziler aslında, java.util.Arrays sınıfının örneklenmiş nesneleridir. Geçen kahve molam dada internetten indirdiğim jsdk dokümanları içinde bu sınıfı aradım ve sayısız pek çok metodunun olduğunu gördüm. Bunların hepsini incelemek için sanıyorum ki bir kaç hektar kahve tarlamın olması, bunları öğütecek ve işlemden geçirerek sütlüsünü, 5 şekerlisini çıkartıp bana sunacak bir fabrikam olması gerekiyor.

Ama sanıyorum ki bu kahve molasında en çok işime yarayacakları incelesem iyi olur. İlk gözüme çarpan aynı isimli metotlardan hemen her veri türü için aşırı yüklenmiş varyasyonların oluşuydu. Örneğin sort metodunu ele alalım. Adından da anlaşılacağı üzere bu metot dizi elemanlarını sıralıyor. Elbette dizinin tipine bağlı olarak gerçekleştirilen bir sıralama bu. Aşağıdaki örnekte, integer değerlerden oluşan bir diziyi şu metot prototipini kullanarak sıralattım.



public static void sort(int[] a)

Şimdide kodlarımızı yazalım.

import java.util.*;

public class DiziSirala


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        System.out.println("Siralanmamis Hali");
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println("");
        System.out.println("Siralanmis Hali");
        Arrays.sort(dizi); 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        } 
    }
}

Burada öncelikle Arrays.sort metodunu kullanarak sıralama işlemini yapmak için, java.util paketini import anahtar kelimesi ile uygulamamıza ekledik. Bu C# taki namespace'lerin using ifadesi ile eklenmesi ile aynı şey. Integer veri türleri için tasarlanmış bu metodun diğer veri türleri için aşırı yüklenmiş versiyonları da mevcut. Burada metodumuz parametre olarak dizinin adını alıyor ve dizinin tipine bakarak uygun olan sort metodunu çalıştırıyor. Sort metodunun bir diğer versiyonu da aşağıda prototipi verilen versiyondur.



public static void sort(int[] a,int fromIndex,int toIndex)

Bu aşırı yüklenmiş versiyona göre, dizinin sadece belirli indisler arasındaki elemanlarının sıralanmasını sağlamış oluyoruz. Bunu yukarıdaki örneğimize uygularsak;

import java.util.*;

public class DiziSirala


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        System.out.println("Siralanmamis Hali");
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println("");
        System.out.println("Siralanmis Hali");
        Arrays.sort(dizi,5,10); 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        } 
    }
}

Bir diğer ilginç metot ise BinarySearch metodu. Sort metodunda olduğu gibi bu metotta diğer tüm veri türleri için aşırı yüklemiş. Prototipi aşağıdaki gibi olan bu metot, dizi içindeki bir elemanın var olup olmadığına bakıyor ve buna göre bir sonuç döndürüyor.



public static int binarySearch(int[] a,int key)

Şimdi bu metod ile ilgili bir deneme yapmanın tam sırası.

import java.util.*;

public class DiziBul


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println(""); 
        int sonuc=Arrays.binarySearch(dizi,56);
        System.out.println("Arama sonucu "+sonuc); 
    }
}

İlk sonuçlar hiçte iç açıcı olmadı benim için. Her şeyden önce aşağıdaki gibi anlamsız bir sonuç elde ettim.

Dokümantasyonu yeniden incelediğimde her şeyin sebebi anlaşılıyordu. BinarySearch metodunu kullanabilmem için, dizinin mutlaka sıralanmış olması gerekiyor. Bu nedenle koda, sort metodunu da ekledim. Bu durumda, dizimizin sıralanmış hali üzerinden arama işlemi başarılı bir şekilde gerçekleştirilmiş oldu. BinarySearch metodunun çalıştırılması sonucu dönen değer, aradığımız elemanın dizi içindeki indis numarasıdır.



import java.util.*;

public class DiziBul


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println(""); 
        Arrays.sort(dizi);
        int sonuc=Arrays.binarySearch(dizi,56);
        System.out.println("Arama sonucu "+sonuc+".eleman"+dizi[sonuc]); 
    }
}

Şimdi daha değişik bir durumu inceleyelim. Eğer dizi içinde olmayan bir eleman ararsak binarySearch metodu nasıl bir sonuç döndürecektir. Bu amaçla aşağıdaki kodu hazırladım. Örnek içinde, iki adet negatif ve iki adet pozitif tamsayıyı dizi içerisinde arattım. Bu elemanların hiçbirisine dizinin bir elemanı değil. Sonuçlara baktığımda dizide olmayan pozifit elemanlar için -12 değerini, dizide olmayan negatif elemanlar için ise -1 değerini elde ettim. Pozifit ve negatif elemanlar için binarySerach metodunun döndürdüğü değerler farklı olmasına rağmen ikisi negatiftir. Dolayısıyla negatif olmaları dizinin elemanı olmadıklarını göstermektedir.



import java.util.*;

public class DiziBul


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println(""); 
        Arrays.sort(dizi);
        int sonuc1=Arrays.binarySearch(dizi,156);
        System.out.println("Arama sonucu "+sonuc1);
        int sonuc2=Arrays.binarySearch(dizi,-8);
        System.out.println("Arama sonucu "+sonuc2);
        int sonuc3=Arrays.binarySearch(dizi,1000);
        System.out.println("Arama sonucu "+sonuc3);
        int sonuc4=Arrays.binarySearch(dizi,-4568);
        System.out.println("Arama sonucu "+sonuc4); 
    }
}

Demek ki binarySearch metodunu bir if koşulu ile kullanarak aranan elemanın dizi içerisinde olup olmadığını belirleyebiliriz.



import java.util.*;

public class DiziBul


{
    public static void main(String[] args)
    { 
        int[] dizi={8,6,3,56,12,3,1,0,23,-1,-5}; 
        for(int i=0;i        {
            System.out.println((i+1)+". eleman="+dizi[i]);
        }
        System.out.println(""); 
        Arrays.sort(dizi);
        int sonuc1=Arrays.binarySearch(dizi,156);
        if(sonuc1<0)
        {
            System.out.println("BULUNAMADI");
        }
        else
        {
            System.out.println("BULUNDU");
        }
    }
}

Arrays sınıfı ile ilgili daha pek çok metot vardı ve bunları incelemek istiyordum. Ama hava aydınlanmaya ve içmeyi unuttuğum kahvemde ice-cafe olmaya başlamıştı. Sanırım ara vermek için en uygun zaman. Biraz dinlenmeyi hak ettik. İlerleyen kahve molalarında kahvemi içmeyi unutmayacağım.

Burak Selim ŞENYURT

selim@buraksenyurt.com 


Yüklə 0,89 Mb.

Dostları ilə paylaş:
1   ...   5   6   7   8   9   10   11   12   ...   23




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©muhaz.org 2024
rəhbərliyinə müraciət

gir | qeydiyyatdan keç
    Ana səhifə


yükləyin