Java'nın Yineleyicisi ve ListIterator öğesi neden öğeler arasında işaret ediyor?


9

ListIterator için Javadoc diyor ki:

A'nın ListIteratorşu anki elemanı yoktur; imleç konumu her zaman çağrıyla döndürülecek previous()öğe ile çağrıyla döndürülecek öğe arasında bulunur next().

Java neden ListIteratorgeçerli bir öğeden ziyade öğeler arasında işaret etmek üzere uygulandı? O defalarca aramak zorunda kaldığında bu istemci kod az okunabilir hale getirdiğini görünüyor getNext(), getPrevious()ben seçim için iyi bir nedeni olmalı varsayalım, böylece.

Bir yan not olarak, ben sadece yazdım biraz kütüphane denilen peekable-arraylist uzanır ArrayList, Iteratorve ListIteratorbu sağlar peekAtNext()ve peekAtPrevious()yöntemleri gibi uygulanan:

  @Override public synchronized T peekAtNext() {
     T t = next();
     previous();
     return t;
  }

2
Guava kütüphanesinde gözlenebilir bir yineleyici vardır code.google.com/p/guava-libraries
kevin

Teşekkürler Kevin! Bu konuda SO bir takip soru gönderdi: Guava'nın ForwardingListIterator bir PeekingIterator ile kullanmak mümkün mü?
glenviewjeff

Yanıtlar:


12

Anlayabildiğim kadarıyla, neden alıntı yapmadığınız javadoc bölümünde bulunabilir (benimkinin altında vurgu):

Programcının listeyi her iki yönde hareket ettirmesine izin veren listeler için yineleyici, yineleme sırasında listeyi değiştirme ...

Gördüğünüz gibi amaçlanan liste değiştirilirken kullanıma izin vermektir. Olası değişiklikler görünüşe göre elemanların çıkarılmasını içerir.

Şimdi current(), yineleyicinin geçerli öğe kavramına sahip olacağını varsayarak yineleyici için bir öğeyi kaldırırsak ne olacağını düşünelim? Bu bağlamda, onu mevcut bir unsur kavramı olmadan uygulamanın yolu benim için oldukça mantıklı - çünkü bu şekilde yineleyici elemanların kaldırılması konusunda endişelenmek zorunda değil.


Öyle önemli parçacığı güvenli olmasını arayüz uygulamaları gerektirmediğini javadoc dikkat etmek.

  • Bu nedenle, farklı iş parçacıklarından yapılan değişikliklerin doğru şekilde işlenmesini beklememelidir - bunun için uygulama, JSR 133 başına Java Bellek Modeli tarafından belirtildiği gibi erişimi senkronize etmek, görünürlük vb .

ListIterator'ın yapabildiği şey, yineleme sırasında aynı iş parçacığından yapılan değişiklikleri işlemektir. Tüm yineleyiciler böyle değildir, ConcurrentModificationException javadocs özellikle bu konuda uyarır:

... Bu istisnanın her zaman bir nesnenin aynı anda farklı bir iş parçacığı tarafından değiştirildiğini göstermediğini unutmayın. Tek bir iş parçacığı, bir nesnenin sözleşmesini ihlal eden bir dizi yöntem çağrısı yayınlarsa, nesne bu özel durumu atabilir. Örneğin, bir iş parçacığı koleksiyonu hızlı bir yineleyici ile koleksiyon üzerinde yineleme yaparken doğrudan değiştirirse, yineleyici bu istisnayı atar ...


1
Ayrıca , ayrı bir şeye ihtiyacınız olmadığı anlamına gelir insertBeforeve insertAfterbu kadar büyük bir sorun olmamasına rağmen remove.
Karl Bielefeldt

1
Peki şu anda mevcut öğeyi aynı anda kaldırabilir ve erişebilir mi? Bu, eşzamanlı olarak çağrılan eşdeğer bir sorun olmaz next()mı? remove()olurdu synchronizedgibi getCurrent(). Bir şey mi kaçırıyorum?
glenviewjeff

@glenviewjeff bu çok iyi bir gözlem. Ayrıca CME'nin orada nasıl ele alınabileceğini merak ediyorum - değişikliklere izin verme niyetinin böyle olması endişe uyandırıyor. Sanırım daha derine inmem gerekiyor. % 99,99 iş parçacığı güvenli olarak tasarlanmadığından eminim, belki sadece aynı iş parçacığından yapılan eşzamanlı modları işleyebilir (tüm yineleyiciler bunu yapamaz, bilirsiniz)
gnat

İlgileniyorsanız, düzenlememe bakın. Bunu gerçekleştirmek için bir uzantı uyguladım ve paketledim ArrayList.
glenviewjeff

@glenviewjeff ilginç. Uygulamanızda next () ve previous () de senkronize ediliyor mu? Eğer sormazsanız, o zaman diğer iş parçacığı şu anki () ortasında bazı beklenmedik hareket sağ "matkap" olabilir, bu istemcinin beklediği gibi davranmak değil yapma ... add () gibi yöntemler de muhtemelen senkronizasyon gerekir
gnat
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.