Простой ответ на « Сбой сортировки потока в бесконечном потоке? » - « Да. » sorted()
- это промежуточная операция с состоянием, которая была реализована путем буферизации все содержимое и сортировка перед передачей любых элементов в последующие операции.
Теоретически так быть не должно. Так как вы используете forEach
, который был явно указан для обработки элементов в неопределенном порядке, шаг сортировки может быть пропущен в вашем new Random().ints().sorted().forEach(System.out::println);
сценарии использования. Но даже если вы использовали forEachOrdered
, есть теоретически достижимый правильный ответ. Поскольку ваш поток бесконечен и будет многократно содержать все значения int
, правильный отсортированный вывод будет печатать -2147483648
(==Integer.MIN_VALUE
) навсегда, поскольку это наименьшее значение, которое содержится в этом потоке бесконечное число раз.
Однако, чтобы дать этот правильный ответ, реализации потребуется конкретный код для обработки этого сценария, что не имеет большого практического значения. Вместо этого реализация обрабатывает этот случай, как и любая другая сортировка потокового сценария, которая завершится неудачей для бесконечных потоков.
В этом конкретном случае поток имеет оптимизацию, которая приводит к другому, необычному сообщению об исключении. Как указал Евгений , этот поток ведет себя как поток фиксированного размера из Long.MAX_VALUE
(==2⁶³
) элементов, а не как действительно бесконечный поток. Это справедливо, учитывая, что поток, генерируемый Random
, будет повторяться после значений 2⁴⁸, поэтому весь поток был повторен 32768 раз, прежде чем он закончится, вместо того, чтобы работать вечно. Вы вряд ли станете свидетелями этого «внезапного» окончания после обработки 9223372036854775807 элементов в любом случае. Но следствием этой оптимизации является то, что поток будет быстро отказывать с сообщением «Размер потока превышает максимальный размер массива», а не с ошибкой «OutOfMemoryError» после некоторой обработки.
Если вы исключите информацию о размере, например, через
new Random().ints().filter(x -> true).sorted().forEach(System.out::println);
операция будет пытаться буферизироваться до сбоя с java.lang.OutOfMemoryError
. То же самое происходит с
IntStream.generate(new Random()::nextInt).sorted().forEach(System.out::println);
, который в первую очередь не предоставляет информацию о размере для потока. В любом случае он никогда ничего не сортирует, поскольку буферизация происходит до начала сортировки.
Если вы хотите получить «отсортированные прогоны для некоторого ограничения элементов», как вы сказали в комментарии, вы должны применить ограничение перед сортировкой, например,
new Random().ints().limit(100).sorted().forEach(System.out::println);
хотя будет еще эффективнее использовать размерный поток, например
new Random().ints(100).sorted().forEach(System.out::println);