Eu estava brincando com o Java 8 lambdas para filtrar facilmente as coleções. Mas não encontrei uma maneira concisa de recuperar o resultado como uma nova lista na mesma declaração. Aqui está a minha abordagem mais concisa até agora:
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);
Os exemplos na rede não responderam à minha pergunta porque eles param sem gerar uma nova lista de resultados. Deve haver uma maneira mais concisa. Eu teria esperado que a Stream
classe tem métodos como toList()
, toSet()
...
Existe alguma maneira de targetLongList
atribuir diretamente as variáveis pela terceira linha?
collections
lambda
java-8
java-stream
Daniel K.
fonte
fonte
sourceLongList
depois,Collection.removeIf(…)
por conveniência.List<Long> targetLongList = sourceLongList.stream().collect(Collectors.toList());
Respostas:
O que você está fazendo pode ser a maneira mais simples, desde que o fluxo permaneça sequencial; caso contrário, você precisará fazer uma chamada para sequencial () antes
forEach
.[editar mais tarde: a razão pela qual a chamada para seqüencial () é necessária é que o código como está (
forEach(targetLongList::add)
) seria atrevido se o fluxo fosse paralelo. Mesmo assim, ele não alcançará o efeito pretendido, comoforEach
é explicitamente não determinístico - mesmo em um fluxo seqüencial a ordem do processamento do elemento não é garantida. Você precisaria usarforEachOrdered
para garantir a ordem correta. A intenção dos designers da API de fluxo é que você use o coletor nesta situação, como abaixo.]Uma alternativa é
fonte
toList
. Isso é feito colocando o seguinte entre as importações do arquivo:static import java.util.stream.Collectors.toList;
. Em seguida, a chamada a cobrar será exibida apenas.collect(toList())
.Collectors
classe em Preferências -> Java -> Editor -> Assistente de Conteúdo -> Favoritos . Depois disso, você só precisará digitartoLi
no hit Ctr + Space para que o IDE preenchatoList
e adicione a importação estática.IntStream
algumas outras quase-mas-não-muito-não-Stream
têm ocollect(Collector)
método e você terá que ligarIntStream.boxed()
para convertê-las para uma regularStream
primeiro. Então, novamente, talvez você só queiratoArray()
.sequential()
antesforEach
ou use 'forEachOrdered`Atualizada:
Outra abordagem é usar
Collectors.toList
:Solução anterior:
Outra abordagem é usar
Collectors.toCollection
:fonte
Collectors::toList
javadoc: "Não há garantias quanto ao tipo, mutabilidade, serialização ou segurança de thread da Lista retornada; se for necessário mais controle sobre a Lista retornada, usetoCollection(Supplier)
".Eu gosto de usar um método util que retorna um coletor para
ArrayList
quando é isso que eu quero.Acho que a solução utilizada
Collectors.toCollection(ArrayList::new)
é um pouco barulhenta para uma operação tão comum.Exemplo:
Com esta resposta, também quero demonstrar como é simples criar e usar coletores personalizados, o que é muito útil em geral.
fonte
toList
se você, por exemplo, deseja modificar a lista posteriormente no programa. AtoList
documentação diz o seguinte: "Não há garantias quanto ao tipo, mutabilidade, serialização ou segurança de thread da Lista retornada; se for necessário mais controle sobre a Lista retornada, usetoCollection
". . Minha resposta demonstra uma maneira de tornar mais conveniente fazer isso em um caso comum.Se você tiver uma matriz de primitivas, poderá usar as coleções primitivas disponíveis nas Coleções Eclipse .
Se você não pode alterar o sourceLongList de
List
:Se você deseja usar
LongStream
:Nota: Sou colaborador do Eclipse Collections.
fonte
Uma maneira um pouco mais eficiente (evite criar a Lista de origem e o unboxing automático pelo filtro):
fonte
Essa é a chamada que você pode usar para converter qualquer fluxo em lista.
mais concretamente:
de:
https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/
fonte
Se você não se importa em usar bibliotecas de terceiros, a lib cyclops-react da AOL (divulgação eu sou um colaborador) possui extensões para todos os tipos de coleções do JDK , incluindo a List . A interface do ListX estende o java.util.List e adiciona um grande número de operadores úteis, incluindo o filtro.
Você pode simplesmente escrever
O ListX também pode ser criado a partir de uma lista existente (via ListX.fromIterable)
fonte
Existe uma outra variante do método collect fornecida pela classe LongStream e da mesma forma pelas classes IntStream e DoubleStream também.
Executa uma operação de redução mutável nos elementos desse fluxo. Uma redução mutável é aquela em que o valor reduzido é um contêiner de resultado mutável, como um ArrayList, e os elementos são incorporados atualizando o estado do resultado e não substituindo o resultado. Isso produz um resultado equivalente a:
Como reduzir (long, LongBinaryOperator), as operações de coleta podem ser paralelizadas sem a necessidade de sincronização adicional. Esta é uma operação do terminal.
E a resposta à sua pergunta com este método de coleta é a seguinte:
Abaixo está a variante de referência do método, que é bastante inteligente, mas algumas são difíceis de entender:
Abaixo, a variante HashSet:
Da mesma forma, a variante LinkedList é assim:
fonte
Caso alguém (como eu) esteja procurando maneiras de lidar com objetos em vez de tipos primitivos, use
mapToObj()
impressões:
fonte
fonte
Aqui está o código de AbacusUtil
Divulgação: sou o desenvolvedor do AbacusUtil.
fonte
com.landawn.abacus.util.stream.LongStream
orLongStreamEx
in AbacusUtilVocê pode reescrever o código como abaixo:
fonte
Para coletar em uma lista mutável:
Para coletar em uma lista imutável:
Explicação dos
collect
do JavaDoc :fonte
Se você não usar
parallel()
isso funcionaráfonte
collect
e depois não salvar o valor de retorno. Nesse caso, você pode usarforEach
. Mas essa ainda é uma solução ruim.