Collections 3 – List Implementation ArrayList
Merhabalar. Önceki yazıda List Interface konusunu işlemiştik. Bu yazıda ArrayList konusuna değineceğiz.
ArrayList, List arabirimini uygulayan yeniden boyutlandırılabilir bir dizi (array) uygulamasıdır (implementation). Bu sayede List Interface içindeki tüm metotları uygular. İçerisine Null dahil olmak üzere tüm veriler atılabilir. Gelecek yazıda göreceğimiz LinkedList ile karşılaştırılması yapıldığında ArrayList’e veri eklemek O(n) zaman alacağı için etkisiz kabul edilir. Halbuki LinkedList’de bu işlem O(1) zamanda gerçekleşmektedir ( Kaynak). ArrayList objeleri varsayılan olarak Synchronized olma özelliğine sahip değildir. Fakat List arabirimini uygulayan bir başka sınıf olan ve ArrayList’e nerede ise eşit kabul edilen Vector sınıfı Synchronized özelliğe sahiptir. Bu şu anlama gelir, bir ArrayList objesi üzerinde bir Thred veri eklemesi yaparken diğer Thred veri silme yapabilir. Fakat aynı durum Vector objesi için geçerli değildir, aynı anda sadece bir Thread Vector objesi üzerinde çalışabilir. List Interface tipindeki listelerimizi synchronized yapmak için şu kodu kullanırız:
List list = Collections.synchronizedList(new ArrayList(...));
Kod içinde Collection sınıfında yer alan synchronizedList metoduna istersek elimizdeki mevcut listeyi istersek de ArrayList constructor çağırımını verebiliriz. Bu durumda list nesnesi verilen parametre sayesinde senkronize özelliğini kazanmış olur.
ArrayList sınıfından nesne oluşturma işlemi sırasında kullanılabilen 3 yapılandırıcı (constructor) metot vardır. Bu metotlar şöyledir:
- ArrayList(): Başlangıç kapasitesi 10 olacak şekilde boş bir liste oluşturur.
- ArrayList(Collection<? extends E> c): Collection Interface’i uygulamış bir nesnenin parametre olarak verilmesi yolu ile ArrayList oluşturulması işlemidir.
- ArrayList(int initialCapacity): Başlangıç kapasitesini bizim belirlediğimiz şekilde liste oluşturur. Boş yapılandırıcı başlangıç kapasitesini 10 olarak belirlerken bu yapılandırıcıda biz belirleriz. Şimdi bu bilgilerin ardından bir uygulama yapalım.
Test
ListAndArrayList.java
ListAndArrayList sınıfı içindeki appMethod metodu içerisinde nameList ve surmaneList adında iki liste oluşturuyoruz. Bu oluşturma işlemi sırasında sol tarafta List arabirimini (interface) kullanıyoruz. Java SE 7 ile birlikte diamond operator denilen işaret ( < > ) collection framework’e eklenmiştir. Bu diaomond operatörleri arasında obje içinde tutulacak değerlerin tipini tanımlıyoruz. Sağ tarafta ise List arabiriminin uygulaması (implementation) olan ArrayList kullanıyoruz. ArrayList’in yanındaki diamond operatörleri arasında ise değerlerin türü yazılmak zorunda değildir. NetBeans ve IntelliJ bu konuda bir şey demezken Eclipse tanımlanmalı şeklinde uyarı vermektedir fakat yazılmaması bir sorun teşkil etmemektedir.
Oluşturulmuş olan ArrayList objelerine değer ekleme işlemi add metodu ile yapılmaktadır. Biz burada sadece değer ekleyen metodu kullandık ama add metodunun 3 faklı varyasyonları daha vardır. Şöyle ki:
[]
Bizim kod içinde kullandığımız add metodu resimdeki 2. sıradaki türdür. 1. türdeki metodda eklemek istediğiniz değeri doğrudan istediğiniz indise koyabilirsiniz. 3.türdeki add metodu elimizdeki ArrayList objesine Collection ya da ondan türetilmiş başka bir koleksiyonun eklenmesine imkan sunar. Örneğin sizin elinizdeki ArrayList objesi içerisine başka bir ArrayList koyabilirsiniz. 1. ve 3. add metotları daima listenin sonuna ekleme yaparlar. Bu açıdan veri ekleme sırasında sıra önemli ise dikkatli olmak gerekir.
Elimizdeki ArrayList’in boyutunu tespit etmek için size() isimli bir metodu vardır. Integer değer döndüren bu metot ArrayList içinde kaç adet değer olduğunu bize bildirir.
List ve onun uygulaması olan ArrayList indisli yapıda olduğu için ArrayList içerisinde indis vasıtası ile bir döngü içinde işlemler yapılabilinir. İndis yapısı 0’dan başladığı için for döngüsü içindeki 0’dan başlayarak işlemlerimizi yapıyoruz ve döngü elimizdeki ArrayList’in boyutuna kadar dönecek. Burada indise bulaşmadan döngü kurmak istersek foreach benzeri bir döngü işimize yarayacaktır. Şöyle ki:
for (String surname:surnameList)
{
System.out.println(surname);
}
Ayrıca şunu belirteyim ki Java 8 ile birlikte Lambda Expressions geldi. Bu yapıyı ve List içinde sunulan foreach metodu ile işlem yapılabilir. Şöyle ki:
surnameList.forEach(e -> System.out.println(e));
Bu kodun çıktısı üstteki for ya da kod içindeki for döngüsünden farklı değildir.
IndexOf metodu kendisine verilen parametreyi listede arar ve indisini bize döndürür.
Get metodu verilen indisdeki verinin ne olduğunu bize söyler.
Listenin boş olup olmadığı isEmpty metodu ile kontrol edilebilir. Eğer boş işse metot true dönecektir, değilse false.
Remove metodunun farklı türden parametre alan iki türevi bulunmaktadır. Birincisinde verilen bir indisdeki veriyi silebilmesi örneklenirken, ikincisinde direk verilen veriyi silmesi örneklenmiştir. Takip eden kodda bu silme sonrası liste ekrana yazdırılıp silme görüntülenmiştir.
Sort metodu listeyi sıralamaya imkan tanır. Örneğimizdeki sort metodu listeyi harflerin sırasına göre sıralamaktadır ve takip eden kod ile ekran çıktısı alınmaktadır.
Sublist metodu bize listenin içinden belli aralıklardaki verileri alarak yeni bir liste elde imkanı sunar. Örnekte 1. ile 3. indis arası veriler alınmıştır. Yalnız burada 3’e kadar alındığına dikkat edelim. Yani hedef indise kadar gidip durur, hedef indisi almaz.
Elimizdeki ArrayList içerisinde işlem yapacağımız zaman Iterator da kullanabiliriz. Yine diamond operatörleri arasında List değişkenimizin tipini yazarak Iterator arabirimi tipinde bir değişken yazıyoruz ve değişkenin oluşturulması işlemi sırasında List arabirimi içerisinde yer alan iterator() metodundan yararlanıyoruz. Bu metot bize Iterator arabirimini uygulamış olan private Itr sınıfından bir obje döndürüyor. Kodumuz içinde surnameList.iterator() diyerek surnameList sınıfı içinde bir iterasyon nesnesi oluşturmuş oluyoruz.
While kodumuz içersinde her döngü dönüşü sırasında hasNext() metodu ile listede takip eden bir eleman daha var mı yok mu onu kotrol ediyoruz. Varsa döngü içerisindeki adımlar yeniden koşturuluyor, yoksa döngü atlanıyor. Başlangıçta listIteration nesnemiz boştur. Bu nedenle Döngü içerisinde iterator.next() diyerek başlıyoruz ve listedeki ilk değeri iterator’a alıyoruz. Akabinde listIterator.remove() diyerek o anki değerin listeden temizlenmesini sağlıyoruz.
Kodun son kısmında da surnameList objemizin boyutunu size() metodu ile kontrol edip listenin gerçekten temizlenip temizlenmediğine bakıyoruz.
Ekran Çıktısı
[]
Bu yazıda List Interface uygulaması olan ArrayList’i ve birtakım metotlarını inceledik. Gelecek yazıda bir başka List uygulaması olan LinkedList’i inceleyeceğiz. Görüşene kadar sağlıcakla kalın.
Bu yazı hazırlanırken şu kaynaklar kullanılmıştır:
https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html