Короткое замыкание потока Java 8

Немного прочитав на Java 8, я получил сообщение этого в блоге, объясняющее немного о потоках и их сокращении, а также, схема сокращения. Внизу указано:

Обратите внимание, что в случае findFirst или findAny нам нужно только первое значение, которое соответствует предикату (хотя findAny не гарантирует возврата первого). Однако, если поток не имеет порядка, то ожидать, что findFirst будет вести себя как findAny. Операции allMatch, noneMatch и anyMatch могут вообще не замыкать поток, поскольку он может оценивать все значения, чтобы определить, является ли оператор true или false. Таким образом, бесконечный поток с их использованием может не завершиться.

Я понимаю, что findFirst или findAny может сократить замыкание, потому что, как только вы найдете элемент, вам больше не нужно обрабатывать.

Но почему это невозможно для allMatch, noneMatch и anyMatch? Для allMatch, если вы найдете тот, который не соответствует предикату, вы можете прекратить обработку. То же самое ни для кого. И anyMatch в особенности не имеет для меня смысла, поскольку он в значительной степени равен findAny (за исключением того, что возвращается)?

Говоря о том, что эти три не могут быть короткозамкнутыми, потому что они могут оценивать все значения, также можно было бы сказать для findFirst/Any.

Есть ли какая-то принципиальная разница, которую я не вижу? Я действительно не понимаю, что происходит?

Ответ 1

Там тонкая разница, потому что anyMatch семья использует предикат, а findAny - нет. Технически findAny() выглядит как anyMatch(x -> true), а anyMatch(pred) выглядит как filter(pred).findAny(). Итак, у нас есть еще одна проблема. Рассмотрим, что мы имеем простой бесконечный поток:

Stream<Integer> s = Stream.generate(() -> 1);

Итак, верно, что применение findAny() к такому потоку всегда будет короткозамкнутым и законченным, а применение anyMatch(pred) зависит от предиката. Однако пусть фильтрует наш бесконечный поток:

Stream<Integer> s = Stream.generate(() -> 1).filter(x -> x < 0);

Является ли результирующий поток бесконечным? Это сложный вопрос. Он фактически не содержит элементов, но чтобы определить это (например, используя .iterator().hasNext()), мы должны проверить бесконечное количество базовых элементов потока, поэтому эта операция никогда не закончится. Я бы назвал такой поток и бесконечным. Однако использование такого потока как anyMatch, так и findAny никогда не закончится:

Stream.generate(() -> 1).filter(x -> x < 0).anyMatch(x -> true);
Stream.generate(() -> 1).filter(x -> x < 0).findAny();

Так что findAny() не гарантируется завершение либо, это зависит от предыдущих операций промежуточного потока.

В заключение я бы оценил этот блог-пост как очень вводящий в заблуждение. По-моему, поведение потока бесконечности лучше объясняется в официальном JavaDoc.

Ответ 2

Отвечено Обновлено

Я бы сказал, что сообщение в блоге неверно, когда оно говорит "findFirst или findAny нам нужно только первое значение, которое соответствует предикату".

В javadoc для allMatch (Predicate), anyMatch (Predicate), noneMatch (Predicate), findAny(), и findFirst():

Это операция короткого замыкания.

Однако обратите внимание, что findFirst и findAny не имеют Predicate. Таким образом, они могут вернуться сразу после просмотра первого/любого значения. Другие 3 являются условными и могут зацикливаться навсегда, если условие никогда не срабатывает.

Ответ 3

Когда javadoc говорит "не может быть короткого замыкания", он просто указывает, что это не короткое замыкание и в зависимости от значений весь поток может быть обработан.

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

Ответ 4

Согласно документации Oracle Stream:  https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps

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

Все пять функций имеют строку:

Это операция короткого замыкания.

В описании функции.

Ответ 5

anyMatch, noneMatch и allMatch возвращают логические значения, поэтому им может потребоваться проверить все, чтобы доказать логику.

findFirst и findAny просто заботиться о том, чтобы найти первое, что они могут, и вернуть это.

Изменить: Для данного набора данных методы Match гарантируют, что всегда будут возвращать одно и то же значение, однако методы Find не связаны с тем, что порядок может меняться и влиять на то, какое значение возвращается.

Описанное короткое замыкание говорит о методах поиска, не имеющих согласованности для данного набора данных.