Saya perlu mencari tahu jumlah elemen di dalam Iterable
di Java. Saya tahu saya bisa melakukan ini:
Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
it.next();
sum++;
}
Saya juga bisa melakukan sesuatu seperti ini, karena saya tidak membutuhkan objek di Iterable lebih jauh:
it = values.iterator();
while (it.hasNext()) {
it.remove();
sum++;
}
Tolok ukur skala kecil tidak menunjukkan banyak perbedaan kinerja, ada komentar atau ide lain untuk masalah ini?
remove()
tanpa meneleponnext()
terlebih dahulu.Jawaban:
TL; DR: Gunakan metode utilitas
Iterables.size(Iterable)
dari pustaka Guava yang hebat .Dari dua cuplikan kode Anda, Anda harus menggunakan yang pertama, karena yang kedua akan menghapus semua elemen dari
values
, jadi setelah itu kosong. Mengubah struktur data untuk kueri sederhana seperti ukurannya sangat tidak terduga.Untuk performa, ini bergantung pada struktur data Anda. Jika itu misalnya pada kenyataannya an
ArrayList
, menghapus elemen dari awal (apa yang dilakukan metode kedua Anda) sangat lambat (menghitung ukurannya menjadi O (n * n) dan bukan O (n) sebagaimana mestinya).Secara umum, jika ada peluang yang
values
sebenarnya adalah aCollection
dan bukan hanya anIterable
, periksa ini dan panggilsize()
jika:if (values instanceof Collection<?>) { return ((Collection<?>)values).size(); } // use Iterator here...
Panggilan untuk
size()
kehendak biasanya jauh lebih cepat daripada menghitung jumlah elemen, dan trik ini adalah apa yangIterables.size(Iterable)
dari Guava lakukan untuk Anda.sumber
values
Jika Anda bekerja dengan java 8, Anda dapat menggunakan:
Iterable values = ... long size = values.spliterator().getExactSizeIfKnown();
ini hanya akan berfungsi jika sumber yang dapat diulang memiliki ukuran yang ditentukan. Sebagian besar Spliterator untuk Koleksi akan melakukannya, tetapi Anda mungkin mengalami masalah jika itu berasal dari
HashSet
atauResultSet
misalnya.Anda dapat memeriksa javadoc di sini.
Jika Java 8 bukan merupakan pilihan , atau jika Anda tidak tahu dari mana iterable berasal, Anda dapat menggunakan pendekatan yang sama seperti guava:
if (iterable instanceof Collection) { return ((Collection<?>) iterable).size(); } else { int count = 0; Iterator iterator = iterable.iterator(); while(iterator.hasNext()) { iterator.next(); count++; } return count; }
sumber
Ini mungkin agak terlambat, tetapi dapat membantu seseorang. Saya menemukan masalah serupa
Iterable
dalam basis kode saya dan solusinya adalah menggunakanfor each
tanpa menelepon secara eksplisitvalues.iterator();
.int size = 0; for(T value : values) { size++; }
sumber
Sebenarnya, Iterable tidak memiliki ukuran. Pikirkan struktur data seperti siklus.
Dan pikirkan tentang mengikuti contoh Iterable, Tanpa ukuran:
new Iterable(){ @Override public Iterator iterator() { return new Iterator(){ @Override public boolean hasNext() { return isExternalSystemAvailble(); } @Override public Object next() { return fetchDataFromExternalSystem(); }}; }};
sumber
Anda dapat mentransmisikan iterable Anda ke daftar lalu menggunakan .size () di atasnya.
Demi kejelasan, metode di atas akan membutuhkan impor berikut:
import com.google.common.collect.Lists;
sumber
Saya akan pergi karena
it.next()
alasan sederhana yangnext()
dijamin akan diterapkan, sedangkanremove()
operasi opsional.sumber
remove
telah dicatat sebagai cara yang salah untuk menghitung elemenIterator
, jadi tidak masalah apakah hal yang tidak akan kita lakukan diterapkan atau tidak.remove
yang dilaksanakan, mengapa itu akan salah untuk menggunakannya? Btw, downvote biasanya digunakan untuk jawaban yang salah atau jawaban yang memberikan nasihat buruk. Saya tidak dapat melihat bagaimana jawaban ini memenuhi syarat untuk semua itu.java 8 ke atas
StreamSupport.stream(data.spliterator(), false).count();
sumber
Bagi saya, ini hanyalah metode yang berbeda. Yang pertama membiarkan objek yang Anda iterasi tidak berubah, sedangkan detik membiarkannya kosong. Pertanyaannya adalah apa yang ingin Anda lakukan. Kompleksitas penghapusan didasarkan pada implementasi objek iterable Anda. Jika Anda menggunakan Koleksi - dapatkan saja ukuran seperti yang diusulkan oleh Kazekage Gaara - biasanya ini merupakan performa pendekatan terbaik yang bijaksana.
sumber
Mengapa Anda tidak menggunakan
size()
metode pada AndaCollection
untuk mendapatkan jumlah elemen?Iterator
hanya dimaksudkan untuk mengulang, tidak ada yang lain.sumber
Iterator
danIterable
. Lihat jawaban yang dipilih untuk cara yang benar.Alih-alih menggunakan loop dan menghitung setiap elemen atau menggunakan dan pustaka pihak ketiga, kita cukup mengetikkan iterable di ArrayList dan mendapatkan ukurannya.
sumber