Подтвердить что ты не робот

Java 8 Lambdas - Побитовые операции И

В настоящее время я занимаюсь проблемой преобразования циклов, которые используют побитовые операции с использованием Lambdas в Java 8.

Учитывая набор сложных записей, требуется, чтобы цикл пересекал ВСЕ записи и вызывал на них заданный метод (метод возвращает логическое значение). Затем верните результат.

Другими словами, мне нужно вызвать метод для всех записей и сохранить результат. Причина в том, что каждая запись независимо выполняет сложную операцию и должна выполняться. Конечный результат представляет собой комбинацию результатов.

Фрагмент кода:

boolean areAllSuccessful = true;
for (SomeEntry entry : entries) {
     areAllSuccessful = areAllSuccessful & entry.doComplexAction(); // keep calling the method on other entries regardless of the result.
}

return areAllSuccessful;

Проблема в том, что функции лямбда в Java 8 обычно выполняют операции короткого замыкания (как только ложная запись обнаружена, "цикл" ломается, и возвращается ложный результат).

Мое лучшее решение до сих пор заключалось в использовании комбинации карт/фильтров/счетчиков:

return entries
       .stream()
       .map(entry -> entry.doComplexAction())
       .filter(result -> result == false)
       .count() > 0

Есть ли более умный/чистый способ сделать это?

Спасибо!

4b9b3361

Ответ 1

Не должно выглядеть так:

boolean areAllSuccessful = entries.stream()
   .map(entry -> entry.isSuccessful())
   .reduce(Boolean.TRUE, Boolean::logicalAnd);

Ответ 2

Самый простой и эффективный способ - использовать ссылку метода с allMatch()

return entries.stream().allMatch(SomeEntry::isSuccessful);

Если у вас есть 1000 элементов, используйте вместо этого parallelStream().

Это не обрабатывает каждый элемент (он возвращается с первой false), поэтому, если ваш метод isSuccessful() имеет побочные эффекты, это плохое имя, и вы должны переименовать его или реорганизовать код для выполнения побочных эффектов в process() (или аналогичном) методе и isSuccessful() возвращает результат, бросая IllegalStateException, если process() не был вызван.

Если вы не реорганизуете, какой-то разработчик (включая вас) вызовет isSuccessful(), не понимая, что он "делает материал", что может быть плохо.

Ответ 3

Вам не нужно map(), если вы собираетесь использовать count():

return !(entries
        .stream()
        .filter(entry -> !entry.isSuccessful())
        .count() > 0);

Если метод isSuccessful() не имел побочных эффектов, и все, что вам нужно знать, было, если все записи были успешными, вы могли бы использовать allMatch():

return entries
        .stream()
        .allMatch(entry -> entry.isSuccessful());

Это действительно операция короткого замыкания, которая вернет false, как только найдет запись, где isSuccessful() - false, не потребляя весь поток, если это необходимо. Но вы уже прокомментировали, что isSuccesful() действительно означает "выполнить некоторые сложные действия, а затем сказать мне, если они были успешными", поэтому он не применяется.