Como converter um mapa para lista em Java?

671

Qual é a melhor maneira de converter um Map<key,value>para um List<value>? Basta iterar sobre todos os valores e inseri-los em uma lista ou estou ignorando alguma coisa?

Javaa
fonte
1
Eu acho que não é um bom modelo se for necessário converter o mapa em lista. Deve-se escrever o código de tal maneira que essa situação não ocorra.
Bugs Hap

Respostas:

1296
List<Value> list = new ArrayList<Value>(map.values());

assumindo:

Map<Key,Value> map;
cleto
fonte
7
Obrigado! Eu estava assumindo que o elenco de Collectionpara Listiria funcionar.
ASGs
1
Eu suspeito que o motivo pelo qual não funcione é porque a coleção retornada por values ​​() depende do mapa subjacente; fazendo uma chamada de construtor de cópia em vez disso, você aloca armazenamento e copiar os valores em que o armazenamento, quebrando assim a conexão ...
Sheldon R.
4
Se tivermos o LinkedHashMap - o pedido continuará o mesmo?
1
@ user2022068 sim, a ordem deve ser preservada com o LinkedHashMap.
SusanW
1
@SheldonR. sim - as coleções retornadas por keySet()e values()geralmente são objetos de calço que fornecem uma visualização de conjunto ou coleção da estrutura subjacente ( keySet()retorna um conjunto para enfatizar não enganos). Pois values(), o objeto retornado pode ser um List, mas geralmente não será. Criar uma lista real, como você diz, quebra o link, o que significa que você não depende mais do mapa original. Às vezes, porém, você só precisa de uma lista, porque alguns API requer um - reforçando a regra de que uma boa API deve exigir apenas as interfaces mais abstratos que podem fugir com ...
SusanW
137

O problema aqui é que Mappossui dois valores (uma chave e um valor), enquanto um Listpossui apenas um valor (um elemento).

Portanto, o melhor que pode ser feito é obter uma Listdas chaves ou os valores. (A menos que façamos um invólucro para manter o par de chave / valor).

Digamos que temos um Map:

Map<String, String> m = new HashMap<String, String>();
m.put("Hello", "World");
m.put("Apple", "3.14");
m.put("Another", "Element");

As chaves como a Listpodem ser obtidas criando um novo ArrayListde um Setretornado pelo Map.keySetmétodo:

List<String> list = new ArrayList<String>(m.keySet());

Enquanto os valores como a Listpodem ser obtidos, crie um novo ArrayListde um Collectionretornado pelo Map.valuesmétodo:

List<String> list = new ArrayList<String>(m.values());

O resultado de obter as Listchaves:

maçã
Outro
Olá

O resultado da obtenção Listdos valores:

3,14
Elemento
Mundo
coobird
fonte
3
Deve-se notar que a ordem dos valores retornados por esses métodos não está definida e, para implementações não HashMapclassificadas semelhantes Map, será efetivamente aleatória.
Joachim Sauer
1
Sim, você precisaria saber que é um LinkedHashMap ou algo desse tipo. O problema com a pergunta original é que a pergunta está incorreta, ou seja, precisa ser editada. A questão não é converter um mapa em uma lista, mas como obter os valores do mapa como uma lista. Os valores do método fornecem uma coleção, mas não uma lista, e, portanto, a necessidade de um pequeno truque.
Demongolem
Acho que você poderia adicionar à sua resposta o que o @ M0les diz: Que você precisaria "seguir" o SortedMap de alguma forma. Comece com uma implementação concreta do SortedMap (como o TreeMap) ou insira seu Mapa de entrada em um SortedMap antes de convertê-lo em Lista
Ignacio Rubio
41

Usando a API Java 8 Streams.

List<Value> values = map.values().stream().collect(Collectors.toList());
Matej Kormuth
fonte
8
Eu prefiro a resposta aceita, baseada em construtor. Os fluxos devem ser para simplificar o código.
Aaron
1
@ Aaron Sim, para a tarefa de obter uma Lista de valores do Mapa, o construtor parece ser mais simples. No entanto, se você estiver usando o Streams extensivamente em uma base de código, é melhor permanecer consistente.
Matej Kormuth 24/02
1
quando eu uso isso, recebo um erro se estou buscando uma quantidade enorme de dados. o thread está em loop no java.util.stream.ReduceOps $ 3.makeSink (fonte desconhecida). Se os threads fizerem um loop infinito, o consumo da CPU começará a aumentar. Looping tópicos Rastreamento de pilha são dadas abaixo, examiná-lo
Ganesh Giri
24

map.entrySet()fornece uma coleção de Map.Entryobjetos contendo chave e valor. você pode transformar isso em qualquer objeto de coleção que desejar, como new ArrayList(map.entrySet());

cara de java
fonte
23

uma lista do que?

Supondo que mapseja sua instância deMap

  • map.values()retornará um Collectioncontendo todos os valores do mapa.
  • map.keySet()retornará um Setcontendo todas as chaves do mapa.
Diego Amicabile
fonte
14

Eu acho que você deseja converter os valores contidos no Mappara a list? O mais fácil é chamar o values()método da Mapinterface. Isso retornará os Collectionobjetos de valor contidos no Map.

Observe que isso Collectioné apoiado pelo Mapobjeto e quaisquer alterações no Mapobjeto serão refletidas aqui. Portanto, se você deseja que uma cópia separada não esteja vinculada ao seu Mapobjeto, basta criar um novo Listobjeto, como ArrayListpassar o valor Collectionabaixo.

ArrayList<String> list = new ArrayList<String>(map.values());
maneesh
fonte
6

Você pode fazer assim

List<Value> list = new ArrayList<Value>(map.values());
user3752441
fonte
1
O OP pergunta sobre como converter em Lista <valor>. Ao fornecer respostas, é melhor incluir uma boa descrição com a solução proposta. Esta pergunta já foi aceita como resposta.
HaveNoDisplayName
5

Se você deseja garantir que os valores no resultante List<Value>estejam na ordem das chaves da entrada Map<Key, Value>, é necessário "continuar"SortedMap alguma forma.

Ou começar com um concreto SortedMapde implementação (tais como TreeMap) ou inserir sua entrada Mapem um SortedMapantes de converter isso para List. por exemplo:

Map<Key,Value> map;
List<Value> list = new ArrayList<Value>( new TreeMap<Key Value>( map ));

Caso contrário, você receberá qualquer ordem nativa Mapfornecida pela implementação, que geralmente pode ser algo diferente da ordem da chave natural (tenteHashtable ou ConcurrentHashMap, para variar).

M0les
fonte
5
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("java", 20);
    map.put("C++", 45);

    Set <Entry<String, Integer>> set = map.entrySet();

    List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);

podemos ter o par de chave e valor na lista. Também podemos obter chave e valor usando Map.Entry iterando a lista.

user11
fonte
4
// you can use this
List<Value> list = new ArrayList<Value>(map.values());

// or you may use 
List<Value> list = new ArrayList<Value>();
for (Map.Entry<String, String> entry : map.entrySet())
{
list.add(entry.getValue());    
}
saurabhgoyal795
fonte
1
"Map<String , String > map = new HapshMap<String , String>;
 map.add("one","java");
 map.add("two" ,"spring");
 Set<Entry<String,String>> set =  map.entrySet();
 List<Entry<String , String>> list = new ArrayList<Entry<String , String>>    (set);
 for(Entry<String , String> entry : list ) {
   System.out.println(entry.getKey());
   System.out.println(entry.getValue());
 } "
siva prasad
fonte
1

Aqui está o método genérico para obter valores do mapa.

public static <T> List<T> ValueListFromMap(HashMap<String, T> map) {
    List<T> thingList = new ArrayList<>();

    for (Map.Entry<String, T> entry : map.entrySet()) {
        thingList.add(entry.getValue());
    }

    return thingList;
}
Hiral Pancholi
fonte
1
HashMap<Integer, List<String>> map = new HashMap<>(); 
List<String> list = new ArrayList<String>();
list.add("Java");
list.add("Primefaces");
list.add("JSF");
map.put(1,list);
if(map != null){
    return new ArrayList<String>((Collection<? extends String>) map.values());
}
Hakan Anlamaz
fonte