"Merhaba, Amigo!"

"Merhaba Ellie!"

"Bugün size yineleyicilerden bahsetmek istiyorum."

"Yineleyiciler pratik olarak koleksiyonlarla aynı zamanda icat edildi. Koleksiyonların temel amacı öğeleri depolamak ve bir yineleyicinin asıl amacı bu öğeleri birer birer geri getirmektir."

"Bir dizi öğe elde etmenin nesi bu kadar zor?"

"Birincisi, Set gibi bazı koleksiyonlardaki öğelerin yerleşik bir düzeni yoktur ve/veya düzen sürekli değişir."

"İkinci olarak, bazı veri yapıları nesneleri çok karmaşık bir şekilde depolayabilir: farklı gruplarda, listelerde vb. Diğer bir deyişle, tüm öğeleri sırayla dağıtmak önemsiz bir görev olacaktır."

"Üçüncüsü, koleksiyonlar değişme eğilimindedir. Bir koleksiyonun tüm içeriğini görüntülemeye karar verdiğinizi varsayalım, ancak çıktının tam ortasında JVM, koleksiyon öğelerinin yarısını değiştiren başka bir diziye geçer. Böylece çıktı yerine, kim bilir neler."

"Hmm..."

"Ama! Bunlar tam olarak bir yineleyicinin çözebileceği türden problemler. Bir yineleyici, bir yandan tüm özel verilerine erişimi olan ve iç yapısını bilen, diğer yandan da bir koleksiyon içindeki özel bir nesnedir. , herkesin onunla nasıl çalışacağını bilmesini sağlayan genel Yineleyici arabirimini uygular. "

"Bazı yineleyiciler, yineleyici oluşturulduğunda koleksiyonun tüm öğelerinin kopyalandığı dahili bir diziye sahiptir. Bu, koleksiyonda sonradan yapılacak değişikliklerin öğelerin sayısını veya sırasını etkilememesini sağlar."

" Her biri için çalışırken bununla karşılaştığınızı düşünüyorum . Aynı anda bir koleksiyon üzerinde döngü yapıp ondan öğeleri kaldıramazsınız. Bunun nedeni tam olarak bir yineleyicinin çalışma şeklidir."

"Eşzamanlılık kitaplığına eklenen yeni koleksiyonlarda, bu sorunu ortadan kaldırmak için iteratör yeniden çalışılmıştır."

"Size bir yineleyicinin nasıl çalıştığını hatırlatmama izin verin."

"Java'nın özel bir Iterator arayüzü var. İşte yöntemleri:"

Iterator<E> arabiriminin yöntemleri Tanım
boolean hasNext() Daha fazla öğe olup olmadığını kontrol eder
E next() Geçerli öğeyi döndürür ve bir sonrakine geçer.
void remove() Geçerli öğeyi kaldırır

"Bir yineleyici, bir koleksiyonun tüm öğelerini arka arkaya almanızı sağlar. Bir yineleyiciyi bir InputStream gibi bir şey olarak düşünmek daha mantıklıdır - tüm verilere sahiptir, ancak görevi bunları sırayla çıkarmaktır."

"Bir   sonraki () yöntemi, koleksiyondaki bir sonraki öğeyi döndürür."

" HasNext () yöntemi, daha fazla öğe olup olmadığını kontrol etmek için kullanılır."

"Ve remove () geçerli öğeyi kaldırır."

"Sorusu olan?"

"Metotların neden bu kadar tuhaf adları var? Neden isEmpty() ve getNextElement() değil?"

"Bu daha mantıklı olmaz mıydı?"

"Daha mantıklı olurdu, ancak adlar, yineleyicilerin daha önce göründüğü C++ dilinden geliyordu."

"Anlıyorum. Devam edelim."

"Yineleyiciye ek olarak, yineleyicileri destekleyen tüm koleksiyonlar tarafından uygulanması gereken Yinelenebilir arabirim de vardır. Tek bir yöntemi vardır:"

Iterable<T> arabiriminin yöntemleri Tanım
Iterator<T>iterator() Bir yineleyici nesnesi döndürür

"Bir yineleyici nesnenin öğeleri arasında gezinmesini sağlamak için bu yöntemi herhangi bir koleksiyonda kullanabilirsiniz. Bir TreeSet'teki tüm öğelerin üzerinden geçelim :"

Örnek
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}

"Bunun gibi bir yineleyici kullanmak pek uygun değil - çok fazla gereksiz ve bariz kod var. Java'da for-each döngüsü göründüğünde durum daha basit hale geldi ."

"Artık bu kod çok daha derli toplu ve okunabilir:"

Önce Sonrasında
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}
TreeSet<String> set = new TreeSet<String>();

for(String item : set)
{
 System.out.println(item);
}

"Bu aynı kod! Yineleyici her iki durumda da kullanılıyor."

"Sadece kullanımı for-each döngüsünde gizli. Sağdaki kodda hiç kırmızı metin olmadığına dikkat edin. Yineleyicinin kullanımı tamamen gizli."

"Yineleyicileri destekleyen herhangi bir nesne için bir for-each döngüsü kullanılabilir. Başka bir deyişle, kendi sınıfınızı yazabilir, buna yineleyici () yöntemini ekleyebilir ve nesnelerini bir for-each yapısında kullanabilirsiniz."

"Vay canına! Elbette, kendi koleksiyonlarımı ve yineleyicilerimi yazmaya hevesli değilim, ama olasılık hâlâ cazip. Bunu bir yere not edeceğim."

Ek olarak, kendi arayüzüne bile sahip olan başka bir popüler yineleyici türü vardır. Listeler için bir yineleyiciden bahsediyorum, yani ListIterator .

"Uygulamaları ne olursa olsun, listeler öğelerin sırasını korur, bu da onlarla bir yineleyici aracılığıyla çalışmayı biraz daha uygun hale getirir."

"İşte ListIterator <E> arabiriminin yöntemleri :"

Yöntem Tanım
boolean hasNext() İleride başka öğe olup olmadığını kontrol eder.
E next() Sonraki öğeyi döndürür.
int nextIndex() Sonraki öğenin dizinini döndürür
void set(E e) Geçerli öğenin değerini değiştirir
boolean hasPrevious() Arkasında herhangi bir öğe olup olmadığını kontrol eder.
E previous() Önceki öğeyi döndürür
int previousIndex() Önceki öğenin dizinini döndürür
void remove() Geçerli öğeyi kaldırır
void add(E e) Listenin sonuna bir öğe ekler.

"Başka bir deyişle, burada hem ileri hem de geri gidebiliriz. Ve birkaç küçük özellik daha var."

"Eh, bu ilginç bir şey. Nerelerde kullanılıyor?"

"Bağlantılı bir listede ileri geri hareket etmek istediğinizi varsayalım. Alma işlemi oldukça yavaş olacak, ancak next() işlemi çok hızlı olacak."

"Hmm. Beni ikna ettin. Bunu aklımda tutacağım."

"Teşekkürler Ellie!"