Java 8 yapıları List<String> stringList
kullanılarak pek çok şekilde yazdırılabilecekleri düşünün :
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)
Bu yaklaşımlar birbirinden nasıl farklı?
İlk Yaklaşım ( Iterable.forEach
) -
Koleksiyonun yineleyicisi genellikle kullanılır ve bu, hızlı bir şekilde tasarlanmıştır; bu da ConcurrentModificationException
, alttaki koleksiyon yineleme sırasında yapısal olarak değiştirilirse atılacağı anlamına gelir . Belirtildiği gibi doc için ArrayList
:
Yapısal bir değişiklik, bir veya daha fazla eleman ekleyen veya silen veya destek dizisini açıkça yeniden boyutlandıran herhangi bir işlemdir; sadece bir elemanın değerinin ayarlanması yapısal bir değişiklik değildir.
Bu nedenle ArrayList.forEach
, değerin ayarlanmasına herhangi bir sorun olmadan izin verilir. Ve eşzamanlı toplama durumunda, örneğin ConcurrentLinkedQueue
yineleyici, zayıf bir şekilde tutarlı olacaktır, bu da, geçirilen eylemlerin forEach
, ConcurrentModificationException
istisnasız olarak bile yapısal değişiklikler yapmasına izin verildiği anlamına gelir . Ancak burada değişiklikler bu yinelemede görülebilir veya görünmeyebilir.
İkinci Yaklaşım ( Stream.forEach
) -
Sipariş tanımsız. Sıralı akışlar için olmasa da, şartname bunu garanti etmez. Ayrıca, eylemin doğaya müdahale etmemesi gerekmektedir. Belirtildiği gibi doc :
Bu operasyonun davranışı açıkça belirsizdir. Paralel akışlı boru hatları için, bu işlem akımın karşılaşma sırasına saygı gösterilmesini garanti etmez, çünkü bunu yapmak paralelliğin faydasını feda edecektir.
Üçüncü Yaklaşım ( Stream.forEachOrdered
) -
Eylem, akışın karşılaşma sırasında gerçekleştirilir. Dolayısıyla, sipariş ne zaman önemli forEachOrdered
olursa, ikinci bir düşünce olmadan kullanın . Belirtildiği gibi doc :
Akış tanımlanmış bir karşılaşma sırasına sahipse, akışın karşılaşma sırasında bu akışın her öğesi için bir eylem gerçekleştirir .
Eşzamanlı bir koleksiyon üzerinde yineleme yaparken , ilk yaklaşım koleksiyonun kilidini bir kez alır ve tüm harekete geçirici mesaj yönteminde tutar, ancak akışlarda, önceden oluşturulmuş olmayan kurallara kilitlenmeyen ve güvenmeyen koleksiyonun ayırıcısını kullanırlar -girişim. Akışın iterasyon sırasında modifiye ConcurrentModificationException
edilmesi durumunda a atılır veya tutarsız bir sonuç ortaya çıkabilir.
Dördüncü Yaklaşım (Paralel Stream.forEach
) -
Daha önce de belirtildiği gibi, paralel akışlarda karşılaşılan sıraya uyulması konusunda herhangi bir garanti verilmemektedir. Eylemin, asla böyle olmayacak farklı elemanlar için farklı bir iş parçacığında gerçekleştirilmesi mümkündür forEachOrdered
.
Beşinci yaklaşım (paralel Stream.forEachOrdered
) -forEachOrdered
akışı, ardışık veya paralel olup bağımsız olarak aslında kaynağı tarafından belirtilen sırada elemanlarını işleyecektir. Bu yüzden bunu paralel akışlarla kullanmak mantıklı değil.
List
? Bize nasıl beyan ettiğinizi ve somutlaştırdığınızı gösterin.