Por favor, considere este código:
System.out.println("#1"); Stream.of(0, 1, 2, 3) .peek(e -> System.out.println(e)) .sorted() .findFirst(); System.out.println("\n#2"); IntStream.range(0, 4) .peek(e -> System.out.println(e)) .sorted() .findFirst();La salida será:
#1 0 1 2 3 #2 0¿Alguien podría explicar por qué la salida de dos flujos es diferente?
Bueno, IntStream.range() devuelve a sequential ordered IntStream from startInclusive(inclusive) to endExclusive (exclusive) by an incremental step of 1 , lo que significa que ya está ordenado. Dado que ya está ordenado, tiene sentido que la siguiente operación intermedia .sorted() no haga nada. Como resultado, peek() se ejecuta solo en el primer elemento (ya que la operación de terminal solo requiere el primer elemento).
Por otro lado, los elementos pasados a Stream.of() no están necesariamente ordenados (y el método of() no verifica si están ordenados). Por lo tanto, .sorted() debe atravesar todos los elementos para producir un flujo ordenado, lo que permite que la operación de terminal findFirst() devuelva el primer elemento del flujo ordenado. Como resultado, peek se ejecuta en todos los elementos, aunque la operación de terminal solo necesita el primer elemento.
IntStream.range ya está ordenado:
// reports true System.out.println( IntStream.range(0, 4) .spliterator() .hasCharacteristics(Spliterator.SORTED) ); Entonces, cuando se activa el método sorted() en Stream, internamente, se convertirá en NO-OP .
De lo contrario, como ya vio en su primer ejemplo, todos los elementos deben ordenarse, solo entonces findFirst puede decir quién es "realmente el primero".
Solo tenga en cuenta que esta optimización solo funciona para secuencias ordenadas de forma natural. Por ejemplo:
// prints too much you say? Stream.of(new User(30), new User(25), new User(34)) .peek(x -> System.out.println("1 : before I call first sorted")) .sorted(Comparator.comparing(User::age)) .peek(x -> System.out.println("2 : before I call second sorted")) .sorted(Comparator.comparing(User::age)) .findFirst();donde (por brevedad):
record User(int age) { }