MERHABA! Son derste sınıfla tanıştık ArrayListve bu derste en yaygın işlemleri nasıl yapacağımızı öğrendik. Ek olarak, bir dizi ile sıradan bir dizi arasındaki birkaç farklılığa dikkat çektik ArrayList. Ancak bir konuyu, yani bir ArrayList. Şimdi bunu tartışacağız. Bir ArrayList'ten bir öğeyi silme - 1Sıradan bir diziden eleman silmenin pek uygun olmadığından daha önce bahsetmiştik. Öğenin kendisini silemeyeceğimiz için, yalnızca değerini "sıfırlayabiliriz" (null olarak ayarlayabiliriz):

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

       System.out.println(Arrays.toString(cats));
   }

   
@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Çıktı: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Ancak bir dizi öğesini null olarak ayarlamak bir "delik" bırakır. Dizideki konumu kaldırmadık, yalnızca içeriğini kaldırdık. 50 kedi dizimiz olsa ve 17 tanesini bu şekilde ortadan kaldırsaydık ne olacağını hayal edin. 17 delikli bir dizimiz olacak. Sadece onları takip etmeye çalışın! Yeni değerler yazabileceğiniz boş hücrelerin sayısını hatırlamayı beklemek gerçekçi değildir. Bir hata yaparsanız, istediğiniz bir nesne referansının üzerine yazarsınız. Elbette bunu biraz daha dikkatli yapmanın bir yolu var: bir elemanı çıkardıktan sonra, "deliği" sonuna koymak için elemanları dizinin önüne taşıyın :

public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Behemoth");
   cats[2] = new Cat("Lionel Messi");
   cats[2] = new Cat("Fluffy");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       cats [i-1] = cats [i];// Move the elements to the front of the array, so the empty position is at the end
   }

   System.out.println(Arrays.toString(cats));
}
Çıktı: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] Bu daha iyi görünüyor, ancak sağlam bir çözüm olarak adlandırılamaz. Bir diziden bir öğeyi her sildiğimizde bu kodu yazmak zorunda olmamızdan başka bir neden yoksa! Bu kötü bir seçenektir. Başka bir yoldan gidebilir ve ayrı bir yöntem oluşturabiliriz:

public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
Ancak bu da çok az işe yarar: bu yöntem yalnızca nesnelerle çalışabilir Cat, diğer türlerle çalışamaz. Yani bir programın dizilerle kullanmak istediğimiz 100 sınıfı daha varsa, her birinde aynı mantığı aynı mantıkla yazmamız gerekecek. Bu tam bir felaket -_- Ama ArrayListsınıf bu sorunu çözüyor! Öğeleri kaldırmak için özel bir yöntem uygular:remove()

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
Nesnemizin dizinini, onu silen yönteme aktarıyoruz (tıpkı bir dizideki gibi). Yöntemin remove()iki özel özelliği vardır. Birincisi, "delikler" bırakmaz. Daha önce kendimiz yazdığımız, ortadan bir eleman kaldırıldığında elemanları kaydırmak için gereken mantığı zaten uyguluyor . Önceki kodun çıktısına bakın:

[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
Bir kediyi ortasından çıkardık ve geri kalanı boş yer kalmayacak şekilde taşındı. İkincisi , nesneleri yalnızca dizine göre (normal bir dizi gibi) değil, aynı zamanda referansa göre de silebilir :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(lionel);

   System.out.println(cats.toString());
}
Çıktı: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Bu, istenen nesnenin dizinini her zaman takip etmek istemiyorsanız çok kullanışlı olabilir. Görünüşe göre normal silme işlemini çözdük. Şimdi şu durumu hayal edelim: listemizi yinelemek ve belirli bir ada sahip bir kediyi kaldırmak istiyoruz . forBunu yapmak için, Rishi'nin derslerinde tanıttığımız hızlı bir döngü (her biri için döngü olarak da adlandırılır) kullanacağız :

public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   for (Cat cat: cats) {

       if (cat.name.equals("Behemoth")) {
           cats.remove(cat);
       }
   }

   System.out.println(cats);
}
Kod tamamen mantıklı görünüyor. Ancak sonuç büyük bir sürpriz olabilir: Java.util.ArrayList$Itr.next(ArrayList. java:831) at Cat.main(Cat.java:25) Bir çeşit hata var ve bunun neden oluştuğu belli değil. Bu süreç, ele alınması gereken bir dizi nüansı içerir. İşte hatırlamanız gereken genel kural: Bir koleksiyon üzerinde aynı anda yineleme yapıp öğelerini değiştiremezsiniz. Ve sadece kaldırmayı değil, herhangi bir değişikliği kastediyoruz. Kedi kaldırma işlemini yeni kediler ekleme girişimiyle değiştirirseniz, sonuç aynı olacaktır:

for (Cat cat: cats) {

   cats.add(new Cat("Salem Saberhagen"));
}

System.out.println(cats);
Java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) adresinde Java.util.ArrayList$Itr.next(ArrayList.java:831) adresinde Cat.main( adresindeki "main" java.util.ConcurrentModificationException iş parçacığında istisna Cat.java:25) Bir işlemi diğerine değiştirdik, ancak sonuç değişmedi: aynı ConcurrentModificationException değerini alıyoruz . Tam olarak, üzerinde yineleme yaparken listeyi değiştirerek yukarıdaki kuralı çiğnemeye çalıştığımızda gerçekleşir. Java'da,bir koleksiyon üzerinde yineleme yaparken öğeleri silmek için yineleyici (IteratorSınıfIterator, öğeler listesi üzerinde güvenli bir şekilde yineleme yapmaktan sorumludur. Sadece 3 yöntemi olduğu için oldukça basit:
  • hasNext()- listede bir sonraki öğe olup olmadığına veya son öğeye zaten ulaştığımıza bağlı olarak doğru veya yanlış döndürür.
  • next()- listedeki bir sonraki öğeyi döndürür
  • remove()- listeden bir öğeyi kaldırır
Gördüğünüz gibi yineleyici ihtiyaçlarımız için özel olarak tasarlandı ve aynı zamanda bu konuda karmaşık bir şey yok. Diyelim ki listemizde bir sonraki öğe olup olmadığını kontrol etmek ve varsa onu görüntülemek istiyoruz:

Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list
  
   Cat nextCat = catIterator.next();// Get the next element
   System.out.println(nextCat);// Display it
}
Çıktı: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} Gördüğünüz gibi, zaten oluşturmak için özel bir yöntem uygulamıştır ArrayList. yineleyici: iterator(). Ek olarak, bir yineleyici oluşturduğumuzda, çalışacağı nesnelerin sınıfını ( <Cat>) belirttiğimizi unutmayın. Sonuç olarak, bir yineleyici, orijinal görevimizi kolayca halleder. Örneğin, "Lionel Messi" adlı kediyi çıkarın:

Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   if (nextCat.name.equals("Lionel Messi")) {
       catIterator.remove();// Delete the cat with the specified name
   }
}

System.out.println(cats);
Çıktı: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Yineleyicininremove() yönteminde ne dizini ne de adı belirtmediğimizi fark etmişsinizdir ! Yineleyici göründüğünden daha akıllıdır: remove()yineleyici tarafından döndürülen son öğeyi kaldırır. Gördüğünüz gibi, tam da yapmasını istediğimiz şeyi yaptı :) Prensip olarak, bir ArrayList. Neredeyse her şey. Bir sonraki derste, bu sınıfın içine bakacağız ve çeşitli yöntem çağrıları sırasında orada neler olduğuna bakacağız :) O zamana kadar!