Java diline biraz yeni gelmek, bir liste (veya belki de diğer koleksiyonlar) ve her birinin avantajları veya dezavantajları aracılığıyla yineleyebileceği tüm yolları (veya en azından patolojik olmayanları) tanımaya çalışıyorum.
Bir List<E> list
nesne göz önüne alındığında , tüm öğeler arasında dolaşmak için aşağıdaki yolları biliyorum:
Döngü için temel (elbette, eşdeğer / döngüler de var)while
do while
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
Not: @amarseillan'ın işaret ettiği gibi, bu form List
s üzerinde yineleme yapmak için kötü bir seçimdir , çünkü get
yöntemin gerçek uygulaması bir Iterator
. Örneğin LinkedList
, i-th öğesini elde etmek için uygulamalar i'den önceki tüm öğeleri geçmelidir.
Yukarıdaki örnekte, List
uygulamanın gelecekteki yinelemeleri daha verimli hale getirmek için "yerini kaydetmesinin" bir yolu yoktur . Çünkü ArrayList
bunun önemi yoktur, çünkü karmaşıklığı / maliyeti get
sabit süredir (O (1)), a için ise LinkedList
listenin büyüklüğü (O (n)) ile orantılıdır.
Yerleşik Collections
uygulamaların hesaplama karmaşıklığı hakkında daha fazla bilgi için bu soruya göz atın .
Döngü için geliştirildi ( bu soruda iyi açıklandı )
for (E element : list) {
// 1 - can call methods of element
// ...
}
yineleyici
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
ListIterator
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
Fonksiyonel Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Her biri için , yinelenebilir .
(Java 8'in Stream API'sinden bir harita yöntemi (@ i_am_zero'nun cevabına bakın).)
Java 8 toplama sınıflarında Iterable
(örneğin, tüm List
s) uygulanan , yukarıda gösterilen for döngüsü ifadesiforEach
yerine kullanılabilecek bir yöntem vardır . (İşte iyi bir karşılaştırma sağlayan başka bir soru .)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
Varsa başka hangi yollar var?
(BTW, ilgim hiç performansı optimize etme arzusundan kaynaklanmıyor ; sadece bir geliştirici olarak hangi formların kullanılabilir olduğunu bilmek istiyorum.)
List
Arayüzle ilgili soru özellikle mi?