🔁 1. Operações não determinísticas

  • Operações como forEach e findAny não garantem ordem em parallelStream.
  • Isso pode melhorar a performance, mas o resultado pode mudar em cada execução.

📌 Exemplo com forEach (não garante ordem):

List numeros = Arrays.asList(1, 2, 3, 4, 5);

numeros.parallelStream()
       .forEach(System.out::print);  // Pode imprimir: 23145, 51324, etc.

✅ Exemplo com forEachOrdered (garante ordem):

numeros.parallelStream()
       .forEachOrdered(System.out::print);  // Sempre: 12345

🔍 2. findAny vs findFirst

  • findAny() retorna qualquer elemento, sem ordem garantida.
  • findFirst() sempre retorna o primeiro elemento, respeitando a ordem do stream.

🔁 Exemplo:

Optional qualquer = numeros.parallelStream().findAny();
Optional primeiro = numeros.parallelStream().findFirst();

📌 3. Ordered vs Unordered Streams

  • Streams de listas (List, LongStream.range) são ordenados por padrão.
  • HashSet, por exemplo, não tem ordem definida.
  • Usar unordered() pode melhorar a performance em paralelismo.

🔁 Exemplo:

Set conjunto = new HashSet<>(Arrays.asList(1, 2, 3));

conjunto.parallelStream()
        .unordered()
        .map(x -> x + 1)
        .forEach(System.out::println); // Pode imprimir: 4, 2, 3

🧩 4. Coletor agrupador paralelo

  • Collectors.groupingBy() mantém a ordem, mas pode ser lento em paralelo.
  • Collectors.groupingByConcurrent() não garante a ordem, mas é mais rápido.

🧪 Exemplo:

Map> agrupado = numeros.parallelStream()
    .collect(Collectors.groupingBy(i -> i % 2 == 0)); // Mantém ordem

Map> agrupadoConcurrente = numeros.parallelStream()
    .collect(Collectors.groupingByConcurrent(i -> i % 2 == 0)); // Melhor performance

⚠️ 5. Efeitos colaterais e variáveis compartilhadas
Usar variáveis compartilhadas em streams paralelos pode causar resultados incorretos.
😵 Exemplo inseguro:

class UnsafeParallelStreamUsage {
    private static long total = 0;

    public static void main(String... args) {
        LongStream.range(0, 1_000_000_000)
                  .parallel()
                  .filter(x -> x % 2 == 0)
                  .forEach(n -> total += n); // ERRO! Concorrência não segura
        System.out.println(total); // Resultados diferentes a cada execução
    }
}

✅ Em vez disso, use sum() ou reduce() que são operações seguras:

long total = LongStream.range(0, 1_000_000_000)
                       .parallel()
                       .filter(x -> x % 2 == 0)
                       .sum(); // Correto

🧠 6. O que é um Spliterator?

  • É uma versão moderna do Iterator, quebrável em partes.
  • Permite que várias threads processem partes diferentes do stream.
  • A paralelização do Stream se baseia nele junto com a API Fork/Join.

Classe de Exemplo completo no repo: ExemploOperacoesStreams