Дозвольте трохи переформатувати ваш приклад задля обговорення:
long runCount = 0L;
myStream.stream()
.filter(...)
.forEach(item -> {
foo();
bar();
runCount++;
});
System.out.println("The lambda ran " + runCount + " times");
Якщо вам дійсно потрібно збільшити лічильник зсередини лямбда, типовий спосіб зробити це - зробити лічильник знаком AtomicInteger
або, AtomicLong
а потім викликати на ньому один із методів збільшення.
Ви можете використовувати одноелемент int
або long
масив, але це матиме умови перегонів, якщо потік запускається паралельно.
Але зауважте, що потік закінчується forEach
, а це означає, що не повертається значення. Ви можете змінити значення forEach
на a peek
, яке пропускає елементи, а потім підрахувати їх:
long runCount = myStream.stream()
.filter(...)
.peek(item -> {
foo();
bar();
})
.count();
System.out.println("The lambda ran " + runCount + " times");
Це дещо краще, але все ж трохи дивно. Причина полягає в тому, що forEach
і peek
може зробити тільки свою роботу з допомогою побічних ефектів. Функціональний стиль Java 8, який виникає, полягає у тому, щоб уникнути побічних ефектів. Ми зробили трохи цього, виділивши приріст лічильника в count
операцію на потоці. Іншими типовими побічними ефектами є додавання предметів до колекцій. Зазвичай їх можна замінити за допомогою колекторів. Але, не знаючи, яку реальну роботу ви намагаєтесь виконати, я не можу запропонувати нічого більш конкретного.