Java Numaralandırması ve Yineleyici arasındaki fark


Yanıtlar:


142

IteratorArayüz için Java API Spesifikasyonuna bakıldığında, aşağıdakiler arasındaki farkların bir açıklaması vardır Enumeration:

Yineleyiciler, numaralandırmalardan iki şekilde farklılık gösterir:

  • Yineleyiciler, çağıranın iyi tanımlanmış anlamlarla yineleme sırasında temeldeki koleksiyondan öğeleri kaldırmasına olanak tanır.
  • Yöntem isimleri iyileştirildi.

Alt çizgi, iki Enumerationve Iteratorbirbirini takip eden elemanlar verecektir, ama Iteratoryöntem adları kısadır, böylece bu şekilde geliştirilir ve ek sahip removeyöntem. İşte yan yana bir karşılaştırma:

  Enumeration                     Iterator
  ----------------                ----------------
  hasMoreElement()                hasNext()
  nextElement()                   next()
  N/A                             remove()

Java API Spesifikasyonlarında da belirtildiği gibi, daha yeni programlar için, "Java koleksiyonları çerçevesinde Numaralandırmanın yerini yineleyici aldığından" Iteratortercih edilmelidir Enumeration. ( IteratorSpesifikasyonlardan.)


9
Sanırım eşzamanlılıkla ilgili bu cevapta eksik bir açıklama var.
Maarten Bodewes

@Paul_Draper: Düzenlemeler gönderiye yeni bir anlam katmamalı, yorumlar bunun içindir.
Emil

2
@coobird "Numaralandırmaların genellikle daha hızlı olduğundan" emin misiniz? Numaralandırma "nextElement () içinde eşitleme bloğu" içerdiğinden Ve EşzamanlıModificationException ritine neden olan Yineleyicilerde Eşitleme'ye sahip değiliz ?? Yineleyiciler genellikle daha hızlıdır ve Numaralandırmalar biraz daha güvenlidir. ??
Kanagavelu Sugumar

@KanagaveluSugumar Bunu işaret ettiğiniz için teşekkür ederiz. (Bu yanıta ek tartışmanın eklendiğini fark etmedim.) Tamamen doğru olmadığı için düzenlemeyi geri aldım.
coobird

Remove () 'un Yineleyici arabiriminde isteğe bağlı bir yöntem olduğunu ve pek çok uygulama sınıfının bunu uygulamadığını belirtmeye değer olduğunu düşünüyorum.
Kutzi

35

Yineleyiciler başarısız olur . yani, bir iş parçacığı toplama / kaldırma işlemleriyle koleksiyonu değiştirdiğinde, başka bir iş parçacığı hasNext() or next()yöntemi kullanarak bir Yineleyici üzerinden geçerken , yineleyici atarak hızla başarısız olur ConcurrentModificationException. Yineleyicilerin hata hızlı davranışı yalnızca hataları tespit etmek için kullanılabilir. Hashtable, Vector gibi sınıfların yöntemleriyle döndürülen Numaralandırmalar, nextElement()çok fazla zamana mal olan geçerli Vector nesnesini kilitleyen yöntem içindeki kod bloğunun senkronize edilmesiyle elde edilen başarısızlık hızlı değildir .


5
Yalnızca kısmen doğru: Bu davranış arayüzde tanımlanmamıştır, Yineleyicinin uygulanmasına bağlıdır. Java.util'deki (HashSet, ArrayList vb.) 'Eski' koleksiyon uygulamalarının bu davranışı sergilediği doğrudur. Ancak, daha yeni 'eşzamanlı' koleksiyonlar hiçbir zaman bir ConcurrentModificationException oluşturmaz, yineleyicinin oluşturulduğu andan itibaren koleksiyonda gezinirler. Diğer uygulamalar hala farklı davranışlar gösterebilir.
Kutzi

1
Ayrıca şuna dikkat edin: "Eşzamanlı olmayan eşzamanlı değişiklik varlığında herhangi bir kesin garanti vermenin imkansız olduğu için başarısızlık hızlı davranışının garanti edilemeyeceğine dikkat edin. Başarısız hızlı işlemler, ConcurrentModificationException'ı en iyi çaba temelinde oluşturur. Bu nedenle , doğruluğu için bu istisnaya bağlı bir program yazmak yanlış olur: ConcurrentModificationException yalnızca hataları tespit etmek için kullanılmalıdır. " docs.oracle.com/javase/7/docs/api/java/util/…
Kutzi

11

"Resmi olarak", fazladan işlemleri (örn. Kaldırma) destekleyen yineleyici arabirimiyle benzer olmaları gerekir. Genel olarak eğilim, yineleyiciler kullanmaktır.

İşte numaralandırma arayüzünden javadocs :

NOT: Bu arabirimin işlevselliği Yineleyici arabirimi tarafından çoğaltılır. Ek olarak, Iterator isteğe bağlı bir kaldırma işlemi ekler ve daha kısa yöntem adlarına sahiptir. Yeni uygulamalar, Numaralandırma yerine Yineleyici kullanmayı düşünmelidir.


6

Basit bir gerçek, ancak daha önceki cevaplarda belirtilmeyen, yapıyı yorumlamak için Iterator<T>birlikte kullanılmasıdır .Iterable<T>for(_type_ element:collection){...}


5

Numaralandırma ve Yineleyicide temel üç fark vardır

Numaralandırma
1. Sadece lagacy sınıfı için kullanılır (örn. Vector)

    Enumeration e = v.elements();  
    v is the object of `Vector` class

2. Okuma işlemi gerçekleştirilebilir, elemanı kaldıramayız.
3. İki Yöntem mevcuttur

  • public boolean hasNextElement ();
  • public Object nextElement ();

yineleyici

  1. tüm Koleksiyon için geçerlidir

    Iterator itr = c.iterator();  
    where c is any `Collection` class
  2. Okuma ve Kaldırma işlemi gerçekleştirilebilir

  3. Üç Yöntem mevcuttur

    • genel boole hasNext ();
    • genel Nesne sonraki ();
    • public void remove ();

Her ikisinde de sınırlama

  • Sadece ileri yönde hareket et
  • Orada hayır için herhangi bir yöntem Add objectveReplace object

2

Kendi koleksiyon sınıfınızı yazıyorsanız ve mevcut sınıflardan herhangi birini genişletiyorsanız veya Koleksiyonlar çerçeve arayüzlerinden herhangi birini uyguluyorsanız, temelde Yineleyiciyi kullanmaktan başka seçeneğiniz yoktur.

Herhangi bir nedenle (aklıma gelmiyor) java.util.Collection veya java.util.Map ile herhangi bir şekilde ilişkili olmayan özel bir koleksiyon sınıfı oluşturuyorsanız, yine de insanların kullanabilmesi için Yinelemeyi uygulamalısınız sınıfınız için döngüler.


2

Başlıca farklı olan, Numaralandırmanın remove () yöntemini göstermemesidir. Dahası, Yineleyici, alttaki bir nesnede aynı anda gezinmeye ve değiştirmeye izin vermez. Eşzamanlı değişiklikler olup olmadığını görmek için bir kontrole sahipler ve bu nedenle daha fazla işlem gerektirir. Dolayısıyla Numaralandırmanın performansı, Yineleyiciden neredeyse% 50 daha hızlıdır. Böyle bir senkronizasyonu göz ardı ederek sadece navigasyona ihtiyacımız varsa, sadece Numaralandırmayı kullanın.


Numaralandırmanın remove () yöntemini "göstermediği" doğrudur - ancak Koleksiyonun remove () api'sinin çağrılmasına da dikkat etmez. Örneğin, aşağıdaki kod yalnızca yazdırılacaktır: AAA, CCC, EEE. -------------------------------------------------- --- Vektör <String> v = new Vector <String> (6); v.add ( "AAA"); v.add ( "BBB"); v.add ( "CCC"); v.add ( "DDD"); v.add ( "iii"); v.add ( "FFF"); Numaralandırma <String> en = v.elements (); while (en.hasMoreElements ()) Dize değeri = (Dize) en.nextElement (); System.out.println (değer); v.remove (değer);
javauser71

1

1) Yineleyici ve Numaralandırma arasındaki temel fark, koleksiyon boyunca gezinirken öğenin kaldırılmasıdır. Yineleyici, remove () yöntemine sahip olduğu için koleksiyonun geçişi sırasında öğeyi kaldırabilir. Numaralandırma, remove () yöntemine sahip değildir.

2) Numaralandırma, doğası gereği güvenli değildir. Koleksiyon geçiş sırasında değiştirilirse ConcurrentModificationException oluşturmaz. Yineleyici, doğası gereği hızlı başarısız olur. Kendi remove () yöntemi dışında yineleme yaparken bir Koleksiyon değiştirilirse ConcurrentModificationException oluşturur.

3) Numaralandırma, Vector, Hashtable'ı geçmek için kullanılan eski bir arayüzdür. Yineleyici, eski bir arayüz değildir. Yineleyici, HashMap, LinkedList, ArrayList, HashSet, TreeMap, TreeSet geçişleri için kullanılabilir.


0

Numaralandırma yalnızca eski sınıf (Vector, Stack ...) için kullanılabilirken, Yineleyici herkes için kullanılabilir.


-1

Verileri almak için hem yineleyici hem de numaralandırma kullanılır, aradaki fark, numaralandırmanın yalnızca eski sınıflar, yani vektör / yığın için kullanılabilirken, yineleyiciler geri kalanı için kullanılabilir olmasıdır. Haritalardaki anahtar seti için numaralandırma da kullanılabilir.


Haritanın anahtar setleri için Numaralamayı kullanabileceğinizi nerede gördünüz?
Kutzi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.