Comportamento de stream.skip com operação de terminal não ordenada
Eu já liesta eesta perguntas, mas ainda duvidam se o comportamento observado deStream.skip
foi planejado pelos autores do JDK.
Vamos ter uma entrada simples dos números 1..20:
List<Integer> input = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
Agora vamos criar um fluxo paralelo, combinar ounordered()
comskip()
de diferentes maneiras e colete o resultado:
System.out.println("skip-skip-unordered-toList: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.skip(1)
.unordered()
.collect(Collectors.toList()));
System.out.println("skip-unordered-skip-toList: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.skip(1)
.collect(Collectors.toList()));
System.out.println("unordered-skip-skip-toList: "
+ input.parallelStream().filter(x -> x > 0)
.unordered()
.skip(1)
.skip(1)
.collect(Collectors.toList()));
A etapa de filtragem basicamente não faz nada aqui, mas acrescenta mais dificuldade ao mecanismo de fluxo: agora ele não sabe o tamanho exato da saída, portanto, algumas otimizações são desativadas. Eu tenho os seguintes resultados:
skip-skip-unordered-toList: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// absent values: 1, 2
skip-unordered-skip-toList: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20]
// absent values: 1, 15
unordered-skip-skip-toList: [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20]
// absent values: 7, 18
Os resultados são completamente bons, tudo funciona como esperado. No primeiro caso, pedi para pular os dois primeiros elementos e depois coletar para listar em nenhuma ordem específica. No segundo caso, pedi para pular o primeiro elemento, depois me tornar desordenado e pular mais um elemento (não me importo com qual deles). No terceiro caso, primeiro entrei no modo não ordenado e depois pulei dois elementos arbitrários.
Vamos pular um elemento e coletar para a coleção personalizada no modo não ordenado. Nossa coleção personalizada será umaHashSet
:
System.out.println("skip-toCollection: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.collect(Collectors.toCollection(HashSet::new)));
A saída é satisfatória:
skip-toCollection: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// 1 is skipped
Então, em geral, espero que, desde que o fluxo seja ordenado,skip()
pula os primeiros elementos, caso contrário, pula os arbitrários.
No entanto, vamos usar uma operação de terminal não ordenada equivalentecollect(Collectors.toSet())
:
System.out.println("skip-toSet: "
+ input.parallelStream().filter(x -> x > 0)
.skip(1)
.unordered()
.collect(Collectors.toSet()));
Agora a saída é:
skip-toSet: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20]
// 13 is skipped
O mesmo resultado pode ser alcançado com qualquer outra operação não ordenada do terminal (comoforEach
, findAny
, anyMatch
etc.). Removendounordered()
passo neste caso não muda nada. Parece que enquantounordered()
Se o passo corretamente fizer com que o fluxo não seja ordenado a partir da operação atual, a operação do terminal não ordenado fará com que todo o fluxo seja desordenado desde o início, apesar de isso poder afetar o resultado seskip()
foi usado. Isso me parece completamente enganador: espero que usar o coletor não ordenado seja o mesmo que transformar o fluxo no modo não ordenadopouco antes da operação do terminal e usando o coletor solicitado equivalente.
Então, minhas perguntas são:
Esse comportamento é intencional ou é um bug?Se sim, está documentado em algum lugar? Eu liStream.skip () documentação: não diz nada sobre operações não-ordenadas do terminal. Além dissoCaracterísticas.UNORDERED a documentação não é muito abrangente e não diz que a ordem será perdida para todo o fluxo. Finalmente,Encomenda A seção no resumo do pacote também não abrange este caso. Provavelmente estou perdendo alguma coisa?Se se pretende que uma operação terminal não ordenada torne todo o fluxo não ordenado, por queunordered()
passo torna desordenado apenas desde este ponto? Posso confiar nesse comportamento? Ou tive sorte de meus primeiros testes funcionarem bem?