Eu tenho uma lista do tipo List<A>
e com a operação de mapa obtendo uma lista coletiva do tipo List<B>
para todos os elementos A mesclados em uma lista.
List<A> listofA = [A1, A2, A3, A4, A5, ...]
List<B> listofB = listofA.stream()
.map(a -> repo.getListofB(a))
.flatMap(Collection::stream)
.collect(Collectors.toList());
sem mapa plano
List<List<B>> listOflistofB = listofA.stream()
.map(a -> repo.getListofB(a))
.collect(Collectors.toList());
Quero recolher os resultados como um mapa do tipo Map<A, List<B>>
e até agora tentando com vários Collectors.toMap
ou Collectors.groupingBy
opções, mas não é capaz de obter o resultado desejado.
java
lambda
java-8
java-stream
collectors
Amitoj
fonte
fonte
A
elementos repetidos no seuList<A>
?Respostas:
Você pode usar o
toMap
coletor com uma referência de método limitada para obter o que precisa. Observe também que esta solução pressupõe que você não tenha repetido instâncias A no seu contêiner de origem. Se essa pré-condição se mantiver, esta solução fornecerá o resultado desejado. Aqui está como fica.Se você duplicou os elementos A, precisará usar essa função de mesclagem além do que é fornecido acima. A função de mesclagem lida com conflitos de teclas, se houver.
E aqui está uma abordagem Java9 muito mais sucinta que usa o
flatMapping
coletor para manipular elementos A repetidos.fonte
Seria direto,
fonte
Para coletar as
Map
chaves where, osA
objetos não são alterados e os valores são a lista dosB
objetos correspondentes , você pode substituir otoList()
coletor pelo seguinte coletor:O primeiro argumento define como calcular a chave do objeto original:
identity()
mantém o objeto original do fluxo inalterado.O segundo argumento define como o valor é calculado; portanto, aqui apenas consiste em uma chamada para o seu método que transforma a
A
em uma lista deB
.Como o
repo
método usa apenas um parâmetro, você também pode melhorar a clareza substituindo o lambda por uma referência de método:fonte
Nesta resposta, estou mostrando o que acontece se você repetir
A
elementos em suaList<A> listofA
lista.Na verdade, se houvesse duplicatas
listofA
, o código a seguir geraria umIllegalStateException
:A exceção pode ser lançada porque
Collectors.toMap
não sabe como mesclar valores quando há uma colisão nas chaves (ou seja, quando a função do mapeador de chaves retorna duplicatas, como seria o casoFunction.identity()
se houvesse elementos repetidos nalistofA
lista).Isso é claramente afirmado nos documentos :
Os documentos também nos fornecem a solução: caso haja elementos repetidos, precisamos fornecer uma maneira de mesclar valores. Aqui está uma dessas maneiras:
Isso usa a versão sobrecarregada
Collectors.toMap
que aceita uma função de mesclagem como seu terceiro argumento. Dentro da função de mesclagem,Collection.addAll
está sendo usado para adicionar osB
elementos de cadaA
elemento repetido em uma lista unqiue para cada umA
.Na função do mapeador de valores, um novo
ArrayList
é criado, para que o originalList<B>
de cadaA
um não seja alterado. Além disso, ao criar umArraylist
, sabemos com antecedência que ele pode ser alterado (ou seja, podemos adicionar elementos a ele posteriormente, caso haja duplicataslistofA
).fonte