Pertimbangkan List<String> stringListyang 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 ConcurrentModificationExceptionjika 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.forEachmenetapkan nilai diperbolehkan tanpa masalah. Dan dalam kasus pengumpulan konkuren misalnya ConcurrentLinkedQueueiterator akan lemah-konsisten yang berarti tindakan forEachyang dilakukan diperbolehkan untuk membuat bahkan perubahan struktural tanpa ConcurrentModificationExceptionkecuali 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 forEachOrderedtanpa 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 ConcurrentModificationExceptionakan 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 forEachOrderedakan 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.
Listsebagai? Tunjukkan kepada kami bagaimana Anda mendeklarasikan dan membuat instance itu.