Sebuah iterator tidak selalu sesuai dengan sesuatu dengan "hitungan" ...
Oliver Charlesworth
Iterator adalah apa adanya; untuk beralih ke objek koleksi berikutnya (bisa berupa apa saja seperti set, array, dll.) Mengapa mereka perlu memberi tahu ukuran ketika mereka tidak peduli untuk apa mereka mencoba mengulang? to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
ecle
Jawaban:
67
Jika Anda baru saja mendapatkan iterator maka itulah yang harus Anda lakukan - iterator tidak tahu berapa banyak item yang tersisa untuk diiterasi, jadi Anda tidak dapat menanyakannya untuk hasil itu. Ada metode utilitas yang tampaknya melakukan ini (seperti Iterators.size()di Guava), tetapi di bawahnya mereka hanya melakukan operasi yang kira-kira sama.
Namun, banyak iterator berasal dari koleksi, yang sering kali dapat Anda kueri untuk ukurannya. Dan jika itu adalah kelas buatan pengguna yang Anda peroleh iteratornya, Anda bisa memberikan metode size () pada kelas itu.
Singkatnya, dalam situasi di mana Anda hanya memiliki iterator maka tidak ada cara yang lebih baik, tetapi lebih sering daripada tidak Anda memiliki akses ke koleksi atau objek yang mendasarinya dari mana Anda mungkin bisa mendapatkan ukurannya secara langsung.
Waspadai efek samping Iterators.size(...)(disebutkan dalam komentar lain di bawah dan di java-doc): "Mengembalikan jumlah elemen yang tersisa di iterator. Iterator akan dibiarkan habis: metode hasNext () akan mengembalikan false." Artinya, Anda tidak dapat menggunakan Iterator lagi setelahnya. Lists.newArrayList(some_iterator);mungkin membantu.
Menggunakan pustaka Guava , opsi lain adalah mengonversi Iterableke a List.
List list =Lists.newArrayList(some_iterator);int count = list.size();
Gunakan ini jika Anda juga perlu mengakses elemen iterator setelah mendapatkan ukurannya. Dengan menggunakan Iterators.size()Anda tidak lagi dapat mengakses elemen iterasi.
@LoveToCode Kurang efisien daripada contoh pada pertanyaan awal
Musim Dingin
2
Tentu, membuat objek baru dengan semua elemen lebih lambat daripada hanya mengulang dan membuang. IMHO, solusi ini adalah satu baris yang meningkatkan keterbacaan kode. Saya sering menggunakannya untuk koleksi dengan sedikit elemen (hingga 1000) atau saat kecepatan tidak menjadi masalah.
tashuhka
7
Jika yang Anda miliki hanyalah iterator, maka tidak, tidak ada cara yang "lebih baik". Jika iterator berasal dari koleksi, Anda bisa menggunakannya untuk ukuran.
Perlu diingat bahwa Iterator hanyalah antarmuka untuk melintasi nilai yang berbeda, Anda akan memiliki kode seperti ini
newIterator<Long>(){finalRandom r =newRandom();@Overridepublicboolean hasNext(){returntrue;}@OverridepublicLong next(){return r.nextLong();}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
atau
newIterator<BigInteger>(){BigInteger next =BigInteger.ZERO;@Overridepublicboolean hasNext(){returntrue;}@OverridepublicBigInteger next(){BigInteger current = next;
next = next.add(BigInteger.ONE);return current;}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
Tidak ada cara yang lebih efisien, jika yang Anda miliki hanyalah iterator. Dan jika iterator hanya dapat digunakan satu kali, maka menghitung sebelum Anda mendapatkan konten iterator adalah ... bermasalah.
Solusinya adalah mengubah aplikasi Anda sehingga tidak memerlukan penghitungan, atau untuk mendapatkan penghitungan dengan cara lain. (Misalnya, berikan lulus Collectiondaripada Iterator...)
objek iterator berisi jumlah elemen yang sama dengan koleksi Anda.
List<E> a =...;Iterator<E> i = a.iterator();int size = a.size();//Because iterators size is equal to list a's size.
Tetapi daripada mendapatkan ukuran iterator dan melakukan iterasi melalui indeks 0 ke ukuran tersebut, lebih baik melakukan iterasi melalui metode next () dari iterator.
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.
penguin.ewu.edu/~trolfe/LinkedSort/Iterator.htmlJawaban:
Jika Anda baru saja mendapatkan iterator maka itulah yang harus Anda lakukan - iterator tidak tahu berapa banyak item yang tersisa untuk diiterasi, jadi Anda tidak dapat menanyakannya untuk hasil itu. Ada metode utilitas yang tampaknya melakukan ini (seperti
Iterators.size()
di Guava), tetapi di bawahnya mereka hanya melakukan operasi yang kira-kira sama.Namun, banyak iterator berasal dari koleksi, yang sering kali dapat Anda kueri untuk ukurannya. Dan jika itu adalah kelas buatan pengguna yang Anda peroleh iteratornya, Anda bisa memberikan metode size () pada kelas itu.
Singkatnya, dalam situasi di mana Anda hanya memiliki iterator maka tidak ada cara yang lebih baik, tetapi lebih sering daripada tidak Anda memiliki akses ke koleksi atau objek yang mendasarinya dari mana Anda mungkin bisa mendapatkan ukurannya secara langsung.
sumber
Iterators.size(...)
(disebutkan dalam komentar lain di bawah dan di java-doc): "Mengembalikan jumlah elemen yang tersisa di iterator. Iterator akan dibiarkan habis: metode hasNext () akan mengembalikan false." Artinya, Anda tidak dapat menggunakan Iterator lagi setelahnya.Lists.newArrayList(some_iterator);
mungkin membantu.Menggunakan pustaka Guava :
Secara internal itu hanya mengulangi semua elemen jadi itu hanya untuk kenyamanan.
sumber
Kode Anda akan memberi Anda pengecualian saat Anda mencapai akhir iterator. Anda bisa melakukan:
Jika Anda memiliki akses ke koleksi yang mendasarinya, Anda akan dapat menghubungi
coll.size()
...EDIT OK, Anda telah mengubah ...
sumber
Anda harus selalu mengulang. Namun Anda bisa menggunakan Java 8, 9 untuk melakukan penghitungan tanpa melakukan perulangan secara eksplisit:
Ini tesnya:
Ini mencetak:
Cukup menarik Anda dapat memparalelkan operasi penghitungan di sini dengan mengubah
parallel
bendera pada panggilan ini:sumber
Menggunakan pustaka Guava , opsi lain adalah mengonversi
Iterable
ke aList
.Gunakan ini jika Anda juga perlu mengakses elemen iterator setelah mendapatkan ukurannya. Dengan menggunakan
Iterators.size()
Anda tidak lagi dapat mengakses elemen iterasi.sumber
Jika yang Anda miliki hanyalah iterator, maka tidak, tidak ada cara yang "lebih baik". Jika iterator berasal dari koleksi, Anda bisa menggunakannya untuk ukuran.
Perlu diingat bahwa Iterator hanyalah antarmuka untuk melintasi nilai yang berbeda, Anda akan memiliki kode seperti ini
atau
sumber
Tidak ada cara yang lebih efisien, jika yang Anda miliki hanyalah iterator. Dan jika iterator hanya dapat digunakan satu kali, maka menghitung sebelum Anda mendapatkan konten iterator adalah ... bermasalah.
Solusinya adalah mengubah aplikasi Anda sehingga tidak memerlukan penghitungan, atau untuk mendapatkan penghitungan dengan cara lain. (Misalnya, berikan lulus
Collection
daripadaIterator
...)sumber
untuk Java 8 Anda bisa menggunakan,
sumber
objek iterator berisi jumlah elemen yang sama dengan koleksi Anda.
Tetapi daripada mendapatkan ukuran iterator dan melakukan iterasi melalui indeks 0 ke ukuran tersebut, lebih baik melakukan iterasi melalui metode next () dari iterator.
sumber
a
, tapi hanyai
?