Как преобразовать карту в список в Java?

675

Каков наилучший способ конвертировать Map<key,value>в List<value>? Просто переберите все значения и вставьте их в список или я что-то пропускаю?

Javaa
источник
1
Я думаю, что это не очень хорошая модель, если нужно конвертировать карту в список. Нужно писать код таким образом, чтобы такая ситуация не возникала.
Ошибки происходят

Ответы:

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

при условии:

Map<Key,Value> map;
Клетус
источник
7
Спасибо! Я предполагал , бросание от Collectionк Listбудет работать.
спрашивает
1
Я подозреваю, что причина этого не в том, что коллекция, возвращаемая values ​​(), зависит от базовой карты; сделав вместо этого вызов конструктора копирования, вы выделяете хранилище и копируете значения в это хранилище, тем самым разрывая соединение ...
Шелдон Р.
4
Если у нас есть LinkedHashMap - заказ останется прежним?
1
@ user2022068 да, порядок должен быть сохранен с LinkedHashMap.
СьюзенW
1
@SheldonR. yes - коллекции, возвращаемые keySet()и, values()как правило, являются объектами-оболочками, которые дают представление Set или Collection базовой структуры ( keySet()возвращает Set, чтобы подчеркнуть отсутствие дубликатов). Ибо values()возвращаемый объект может быть List, но часто не будет. Создание настоящего Списка, как вы говорите, нарушает ссылку, что означает, что вы больше не зависите от исходной Карты. Иногда, однако, вам нужен только List, потому что некоторые API требуют одного - усиливая правило, что хороший API должен требовать только самых абстрактных интерфейсов, с
которыми
137

Проблема здесь в том, что у Mapнего есть два значения (ключ и значение), в то время как a Listимеет только одно значение (элемент).

Поэтому лучшее, что можно сделать, - это получить Listключи или значения. (Если только мы не создадим оболочку для пары ключ / значение).

Скажем, у нас есть Map:

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

Ключи Listможно получить, создав новый ArrayListиз Setвозвращенного Map.keySetметодом:

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

Тогда как значения Listможно получить, создав новый ArrayListиз Collectionвозвращенного Map.valuesметодом:

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

Результат получения Listключей:

яблоко
Другая
Привет

Результат получения Listзначений:

3,14
Элемент
Мир
coobird
источник
3
Следует отметить, что порядок значений, возвращаемых этими методами, не определен, и для HashMapаналогичных несортированных Mapреализаций он будет фактически случайным.
Йоахим Зауэр
1
Да, вы должны знать, что это LinkedHashMap или что-то в этом роде. Проблема с оригинальным вопросом состоит в том, что вопрос искажен, то есть требует редактирования. Вопрос не в том, чтобы преобразовать карту в список, а в том, как получить значения карты в виде списка. Значения метода дают вам коллекцию, но не список, и, следовательно, необходимость в аккуратной маленькой хитрости.
демонголем
Я думаю, что вы могли бы добавить к своему ответу то, что говорит @ M0les: что вам нужно как-то "пройти через" SortedMap. Либо начните с конкретной реализации SortedMap (например, TreeMap), либо вставьте входную карту в SortedMap перед преобразованием ее в List
Ignacio Rubio
41

Использование Java 8 Streams API.

List<Value> values = map.values().stream().collect(Collectors.toList());
Матей Кормут
источник
8
Я предпочитаю принятый, основанный на конструкторе ответ. Потоки должны быть для упрощения кода.
Аарон,
1
@Aaron Да, для задачи получения списка значений из Map конструктор выглядит проще. Однако, если вы используете Streams экстенсивно в кодовой базе, лучше оставаться последовательным.
Матей Кормут,
1
когда я использую это, получаю ошибку, если я получаю огромное количество данных .. поток зацикливается на java.util.stream.ReduceOps $ 3.makeSink (Неизвестный источник). Если потоки бесконечно зацикливаются, загрузка процессора начнет расти. Трассировка стека циклических потоков приведена ниже, изучите ее
Ганеш Гири,
24

map.entrySet()дает вам коллекцию Map.Entryобъектов, содержащих как ключ, так и значение. затем вы можете преобразовать это в любой объект коллекции, который вам нравится, например new ArrayList(map.entrySet());

ява чувак
источник
23

список чего?

Предположим, mapэто ваш примерMap

  • map.values()вернет Collectionсодержащий все значения карты.
  • map.keySet()вернет Setсодержащий все ключи карты.
Диего Амикабиле
источник
14

Я предполагаю , что вы хотите , чтобы преобразовать значения , содержащиеся в Mapк list? Проще всего вызвать values()метод Mapинтерфейса. Это вернет Collectionобъекты значения, содержащиеся в Map.

Обратите внимание, что это Collectionподдерживается Mapобъектом, и любые изменения в Mapобъекте будут отражены здесь. Поэтому, если вы хотите, чтобы отдельная копия не была привязана к вашему Mapобъекту, просто создайте новый Listобъект, например, ArrayListпередав значение, Collectionкак показано ниже.

ArrayList<String> list = new ArrayList<String>(map.values());
Maneesh
источник
6

Вы можете сделать это так

List<Value> list = new ArrayList<Value>(map.values());
user3752441
источник
1
ОП спросить о том, как преобразовать в список <значение>. Когда предоставите ответы, лучше включить хорошее описание с предлагаемым решением. На этот вопрос уже принят ответ.
HaveNoDisplayName
5

Если вы хотите убедиться, что значения в результате List<Value>находятся в порядке клавиш ввода Map<Key, Value>, вам нужно «пройти через»SortedMap .

Либо начните с конкретной SortedMapреализации (например, TreeMap), либо вставьте свой вход Mapв, SortedMapпрежде чем преобразовать его в List. например:

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

В противном случае вы получите то, что Mapобеспечивает реализация в собственном порядке , что часто может быть чем-то отличным от упорядочения естественного ключа (Try Hashtableили ConcurrentHashMap, для разнообразия).

M0les
источник
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);

у нас может быть пара ключей и значений в списке. Также можно получить ключ и значение, используя Map.Entry, перебирая список.

user11
источник
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
источник
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());
 } "
Шива Прасад
источник
1

Вот общий метод для получения значений из карты.

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
источник
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());
}
Хакан Анламаз
источник