Pertimbangkan List<String> stringList
yang dapat dicetak dalam banyak cara menggunakan konstruksi Java 8 :
stringList.forEach(System.out::println); // 1) Iterable.forEach
stringList.stream().forEach(System.out::println); // 2) Stream.forEach (order maintained generally but doc does not guarantee)
stringList.stream().forEachOrdered(System.out::println); // 3) Stream.forEachOrdered (order maintained always)
stringList.parallelStream().forEach(System.out::println); // 4) Parallel version of Stream.forEach (order not maintained)
stringList.parallelStream().forEachOrdered(System.out::println); // 5) Parallel version ofStream.forEachOrdered (order maintained always)
Bagaimana pendekatan ini berbeda satu sama lain?
Pendekatan Pertama ( Iterable.forEach
) -
Iterator koleksi umumnya digunakan dan yang dirancang untuk gagal-cepat yang berarti akan dibuang ConcurrentModificationException
jika koleksi yang mendasarinya secara struktural dimodifikasi selama iterasi. Sebagaimana disebutkan dalam dokumen untuk ArrayList
:
Modifikasi struktural adalah setiap operasi yang menambah atau menghapus satu atau lebih elemen, atau secara eksplisit mengubah ukuran backing array; hanya pengaturan nilai suatu elemen bukanlah modifikasi struktural.
Jadi itu berarti untuk ArrayList.forEach
menetapkan nilai diperbolehkan tanpa masalah. Dan dalam kasus pengumpulan konkuren misalnya ConcurrentLinkedQueue
iterator akan lemah-konsisten yang berarti tindakan forEach
yang dilakukan diperbolehkan untuk membuat bahkan perubahan struktural tanpa ConcurrentModificationException
kecuali dilemparkan. Tapi di sini modifikasi mungkin atau mungkin tidak terlihat dalam iterasi itu.
Pendekatan Kedua ( Stream.forEach
) -
Pesanan tidak ditentukan. Meskipun mungkin tidak terjadi untuk aliran berurutan tetapi spesifikasi tidak menjaminnya. Juga tindakan tersebut dituntut untuk tidak mengganggu. Seperti disebutkan dalam dokumen :
Perilaku operasi ini secara eksplisit tidak deterministik. Untuk pipa aliran paralel, operasi ini tidak menjamin untuk menghormati urutan pertemuan arus, karena hal itu akan mengorbankan manfaat paralelisme.
Pendekatan Ketiga ( Stream.forEachOrdered
) -
Tindakan akan dilakukan dalam urutan pertemuan aliran. Jadi, kapan pun pesanan penting digunakan forEachOrdered
tanpa pikir panjang. Sebagaimana disebutkan dalam dokumen :
Melakukan tindakan untuk setiap elemen aliran ini, dalam urutan pertemuan aliran jika aliran memiliki urutan pertemuan yang ditentukan.
Sementara iterasi pada koleksi yang disinkronkan , pendekatan pertama akan mengambil kunci koleksi sekali dan akan menahannya di semua panggilan untuk metode tindakan, tetapi dalam kasus stream mereka menggunakan kumpulan spliterator, yang tidak mengunci dan bergantung pada aturan non -gangguan. Dalam kasus pengumpulan dukungan, aliran dimodifikasi selama iterasi yang ConcurrentModificationException
akan dilempar atau hasil yang tidak konsisten dapat terjadi.
Pendekatan Keempat (Paralel Stream.forEach
) -
Seperti yang telah disebutkan tidak ada jaminan untuk menghormati urutan pertemuan seperti yang diharapkan dalam kasus aliran paralel. Ada kemungkinan bahwa tindakan dilakukan dalam utas yang berbeda untuk elemen yang berbeda yang tidak akan pernah terjadi forEachOrdered
.
Pendekatan Kelima (Paralel Stream.forEachOrdered
) -
Proses forEachOrdered
akan elemen dalam urutan yang ditentukan oleh sumber terlepas dari fakta apakah aliran berurutan atau paralel. Jadi tidak masuk akal untuk menggunakan ini dengan aliran paralel.
List
sebagai? Tunjukkan kepada kami bagaimana Anda mendeklarasikan dan membuat instance itu.