Java: Cara terbaik untuk mengulang melalui Koleksi (di sini ArrayList)

98

Hari ini saya dengan senang hati membuat kode ketika saya mendapatkan sepotong kode yang sudah saya gunakan ratusan kali:

Iterasi melalui Koleksi (di sini ArrayList)

Untuk beberapa alasan, saya benar-benar melihat opsi pelengkapan otomatis Eclipse dan itu membuat saya bertanya-tanya:

Kasus apa yang lebih baik digunakan loop berikut daripada yang lain?

Loop indeks array klasik:

for (int i = 0; i < collection.length; i++) {
  type array_element = collection.get(index);
}

Iterator hasNext () / next ():

for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
  type type = (type) iterator.next();   
}

Dan favorit saya karena sangat mudah untuk menulis:

for (iterable_type iterable_element : collection) {

}
Jason Rogers
sumber
2
Ketika datang ke saya, saya kebanyakan menggunakan loop ke-3.
Harry Joy
1
Untuk cara kedua lebih baik menggunakan:for (Iterator<type> iterator = collection.iterator(); iterator.hasNext();) { type type = iterator.next(); }
mike jones
4
Antarmuka koleksi tidak berisi metode "get", jadi yang pertama tidak selalu memungkinkan.
ThePerson

Jawaban:

104

Yang pertama berguna saat Anda membutuhkan indeks elemen juga. Ini pada dasarnya sama dengan dua varian lainnya untuk ArrayLists, tetapi akan sangat lambat jika Anda menggunakan file LinkedList.

Yang kedua berguna ketika Anda tidak membutuhkan indeks elemen tetapi mungkin perlu menghapus elemen saat Anda mengulang. Tapi ini memiliki kelemahan karena IMO terlalu bertele-tele.

Versi ketiga adalah pilihan saya juga. Ini singkat dan berfungsi untuk semua kasus di mana Anda tidak memerlukan indeks atau iterator yang mendasarinya (yaitu Anda hanya mengakses elemen, tidak menghapusnya atau memodifikasi dengan Collectioncara apa pun - yang merupakan kasus paling umum).

MAK
sumber
3
+1 Kalahkan saya untuk itu. akan menyebutkan LinkedList (tidak semuanya Collection murah untuk diambil dengan indeks).
The Scrum Meister
Selama seseorang hanya perlu mengulang elemen, itu selalu baik untuk menggunakan versi ke-3, karena implementasi sudah ada untuk semua Koleksi yang berbeda dan Sun atau implementasi JDK berusaha untuk meningkatkan kinerja daripada setiap satu.
Phani
@Phani: Dua varian lainnya juga berfungsi pada implementasi JDK apa pun.
MAK
Saya tidak mengatakan bahwa itu tidak akan berfungsi, tetapi jika kebetulan perbaikan atau perubahan kinerja tertentu dilakukan untuk implementasi koleksi, maka itu akan secara otomatis berlaku untuk kode Anda dan Anda tidak perlu menulis untuk meningkatkan kinerja adalah yang saya maksud.
Phani
1
@Phani: AFAIK bentuk ke-3 hanyalah gula sintaksis untuk bentuk ke-2 (yaitu, di bawah kap, setiap varian sebenarnya menggunakan iterator). Jadi, manfaat performa apa pun harus tersedia untuk kedua varian. Versi pertama tentu saja tidak akan mendapatkan keuntungan kinerja apa pun (misalnya jika Listditerapkan sebagai pohon, sebenarnya akan lebih lambat).
MAK
36

Semuanya memiliki kegunaannya sendiri:

  1. Jika Anda memiliki iterable dan perlu melintasi tanpa syarat ke semuanya:

    untuk (iterable_type iterable_element: collection)

  2. Jika Anda memiliki iterable tetapi perlu melintasi secara kondisional:

    untuk (Iterator iterator = collection.iterator (); iterator.hasNext ();)

  3. Jika struktur data tidak menerapkan iterable:

    untuk (int i = 0; i <collection.length; i ++)

Suraj Chandran
sumber
Dapatkah Anda melakukan ini untuk melintasi metode pertama secara bersyarat: if (iterable_element.some_attribute) {// do something; } lain {// tidak melakukan apa-apa; }. Jika ya maka pada dasarnya tidak ada perbedaan antara metode pertama dan kedua, selain gula sintaksis.
Thomas Nguyen
1 sama mampu melintasi bersyarat seperti yang lain menggunakan breakdan / ataucontinue
arcyqwerty
13

Ada juga koleksi 'stream () util dengan Java 8

collection.forEach((temp) -> {
            System.out.println(temp);
});

atau

collection.forEach(System.out::println);

Informasi lebih lanjut tentang aliran Java 8 dan tautan koleksi untuk keajaiban

snr
sumber
4

Tak satu pun dari mereka yang "lebih baik" dari yang lain. Yang ketiga, bagi saya, lebih mudah dibaca, tetapi bagi seseorang yang tidak menggunakan foreaches ini mungkin terlihat aneh (mereka mungkin lebih suka yang pertama). Ketiganya cukup jelas bagi siapa saja yang memahami Java, jadi pilih mana yang membuat Anda merasa lebih baik tentang kodenya.

Yang pertama adalah yang paling dasar, jadi ini adalah pola paling universal (berfungsi untuk array, semua iterable yang dapat saya pikirkan). Itulah satu-satunya perbedaan yang dapat saya pikirkan. Dalam kasus yang lebih rumit (misalnya Anda perlu memiliki akses ke indeks saat ini, atau Anda perlu memfilter daftar), kasus pertama dan kedua mungkin lebih masuk akal. Untuk kasus sederhana (objek yang dapat diulang, tidak ada persyaratan khusus), yang ketiga tampaknya yang paling bersih.

Rafe Kettler
sumber
2

Opsi pertama adalah kinerja yang lebih baik (Karena ArrayList mengimplementasikan antarmuka RandomAccess). Sesuai dengan dokumen java, implementasi List harus mengimplementasikan antarmuka RandomAccess jika, untuk instance kelas yang khas, loop ini:

 for (int i=0, n=list.size(); i < n; i++)
     list.get(i);

berjalan lebih cepat dari loop ini:

 for (Iterator i=list.iterator(); i.hasNext(); )
     i.next();

Saya harap ini membantu. Opsi pertama akan lambat untuk daftar akses berurutan.

Amitav Padhi
sumber
1

Berikut ini contohnya

Query query = em.createQuery("from Student");
             java.util.List list = query.getResultList();
             for (int i = 0; i < list.size(); i++) 
             {

                 student = (Student) list.get(i);
                 System.out.println(student.id  + "  " + student.age + " " + student.name + " " + student.prenom);

             }
Abdelouhab
sumber