No JDK 8 com lambda b93, havia uma classe java.util.stream.Streams.zip no b93 que poderia ser usada para compactar fluxos (isso é ilustrado no tutorial Explorando o Java8 Lambdas. Parte 1 de Dhananjay Nene ). Esta função:
Cria um fluxo combinado lento e sequencial cujos elementos são o resultado da combinação dos elementos de dois fluxos.
No entanto, em b98 isso desapareceu. De fato, a Streams
classe não está acessível em java.util.stream no b98 .
Essa funcionalidade foi movida e, em caso afirmativo, como faço para compactar fluxos de forma concisa usando o b98?
O aplicativo que tenho em mente é nesta implementação em Java do Shen , onde substituí a funcionalidade zip no
static <T> boolean every(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)
static <T> T find(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)
funciona com código bastante detalhado (que não usa a funcionalidade do b98).
Respostas:
Eu também precisava disso, então peguei o código fonte do b93 e o coloquei em uma classe "util". Eu tive que modificá-lo um pouco para trabalhar com a API atual.
Para referência, aqui está o código de trabalho (corra por seu próprio risco ...):
fonte
SIZED
se um deles éSIZED
, não os dois?SIZED
para que essa implementação funcione. Na verdade, depende de como você define o zíper. Você deve poder compactar dois fluxos de tamanho diferente, por exemplo? Como seria o fluxo resultante então? Acredito que é por isso que essa função foi realmente omitida da API. Há muitas maneiras de fazer isso e cabe ao usuário decidir qual comportamento deve ser o "correto". Você descartaria os elementos do fluxo mais longo ou preencheria a lista mais curta? Se sim, com que valor (es)?Spliterator<A>
).zip é uma das funções fornecidas pela biblioteca protonpack .
fonte
Se você possui o Guava em seu projeto, pode usar o método Streams.zip (adicionado no Guava 21):
fonte
Compactando dois fluxos usando JDK8 com lambda ( gist ).
fonte
import java.util.function.*;
eimport java.util.stream.*;
na parte superior do seu arquivo.() -> iterator
e aqui novamente:iterable.spliterator()
. Por que não implementar diretamente um emSpliterator
vez de umIterator
? Verificar @Doradus answer stackoverflow.com/a/46230233/1140754Como não consigo conceber nenhum uso de zipar em coleções que não sejam indexadas (Listas) e sou um grande fã de simplicidade, esta seria minha solução:
fonte
mapToObject
deveria sermapToObj
.RandomAccess
(por exemplo, nas listas vinculadas), isso será muito lentoOs métodos da classe que você mencionou foram movidos para a
Stream
própria interface em favor dos métodos padrão. Mas parece que ozip
método foi removido. Talvez porque não esteja claro qual deve ser o comportamento padrão para fluxos de tamanhos diferentes. Mas implementar o comportamento desejado é direto:fonte
predicate
passou para o filtro com estado ? Isso viola o contrato do método e, especialmente, não funciona ao processar o fluxo em paralelo.Eu humildemente sugiro esta implementação. O fluxo resultante é truncado para o menor dos dois fluxos de entrada.
fonte
.., leftStream.isParallel() || rightStream.isParallel()
. Eu acho que não tem efeito, porqueAbstractSpliterator
oferece paralelismo limitado por padrão. Então eu acho que o resultado final será o mesmo que passarfalse
.A biblioteca Lazy-Seq fornece funcionalidade zip.
https://github.com/nurkiewicz/LazySeq
Esta biblioteca é fortemente inspirada
scala.collection.immutable.Stream
e visa fornecer uma implementação de sequência lenta, imutável, segura para threads e fácil de usar, possivelmente infinita.fonte
Usando a biblioteca Guava mais recente (para a
Streams
classe), você poderá fazerfonte
Isso funcionaria para você? É uma função curta, que avalia preguiçosamente os fluxos que estão sendo compactados, para que você possa fornecê-los com fluxos infinitos (não é necessário ter o tamanho dos fluxos sendo compactados).
Se os fluxos são finitos, eles param assim que um dos fluxos fica sem elementos.
Aqui está um código de teste de unidade (muito mais longo que o próprio código!)
fonte
takeWhile
no final era que não parece estar em java8, mas não é um problema, pois o receptor pode filtrar quaisquer valores nulos que ocorrem quando os fluxos compactados não são do mesmo tamanho. Eu acho que essa resposta deve ser a resposta número 1, pois é consistente e compreensível. ótimo trabalho obrigado novamente.fonte
O cyclops-react da AOL , com o qual contribuo, também fornece a funcionalidade de compactar, tanto por meio de uma implementação estendida do Stream , que também implementa a interface do reative-streams ReactiveSeq quanto pelo StreamUtils, que oferece grande parte da mesma funcionalidade por métodos estáticos aos Java Streams padrão.
Ele também oferece um zíper baseado em aplicativo mais generalizado. Por exemplo
E até a capacidade de emparelhar todos os itens em um fluxo com todos os itens em outro
fonte
Se alguém precisar disso ainda, há uma
StreamEx.zipWith
função na biblioteca streamex :fonte
Isso é ótimo. Eu tive que compactar dois fluxos em um mapa, com um fluxo sendo a chave e outro sendo o valor
Saída: {A = Maçã, B = Banana, C = Cenoura}
fonte