802

How do I convert a Map<key,value> to a List<value>? Should I iterate over all map values and insert them into a list?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Javaa
  • 8,059
  • 3
  • 17
  • 5
  • 1
    I think it's not a good model if one has to convert map into list. One should write the code in such manner that this situation doesn't arrise. – Bugs Happen Dec 05 '17 at 17:13

13 Answers13

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

assuming:

Map<Key,Value> map;
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 12
    Thanks! I was assuming the cast from `Collection` to `List` would work. – asgs Jun 18 '13 at 21:28
  • 1
    I suspect the reason it doesn't work is because the collection returned by values() is dependent on the underlying Map; by making a copy constructor call instead, you allocate storage and copy the values into that storage, thus breaking the connection... – Sheldon R. Nov 22 '13 at 16:14
  • 4
    If we have LinkedHashMap - will the order leave the same? –  Jun 06 '15 at 18:42
  • 1
    @user2022068 yes, order should be preserved with LinkedHashMap. – SusanW Sep 09 '16 at 10:16
  • 2
    @SheldonR. yes - the collections returned by `keySet()` and `values()` are generally shim objects that give a Set or Collection view of the underlying structure (`keySet()` returns a Set to emphasize no dupes). For `values()`, the returned object _may_ be a `List`, but often won't be. Creating a real List, as you say, breaks the link which means you're no longer dependent on the original Map. Sometimes though, you only need a List because some API requires one - reinforcing the rule that a good API should require only the most abstract interfaces it can get away with... – SusanW Sep 09 '16 at 10:26
  • 1
    That's perfect, just let's use the diamond operator in the ArrayList constructor: List list = new ArrayList<>(map.values()); – Nestor Milyaev Jan 24 '17 at 16:08
  • 1
    In my case (Java 8, IntellijJ) the compiler just fails with type inferring `new ArrayList(map.values())`; have to change it to `new ArrayList(map.values())` and only get a warning is shown. – WesternGun Jul 05 '19 at 10:57
  • @WesternGun Try `new ArrayList<>(map.values())`, this will get rid of all warnings – Jasperan Apr 11 '22 at 16:29
144

The issue here is that Map has two values (a key and value), while a List only has one value (an element).

Therefore, the best that can be done is to either get a List of the keys or the values. (Unless we make a wrapper to hold on to the key/value pair).

Say we have a Map:

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

The keys as a List can be obtained by creating a new ArrayList from a Set returned by the Map.keySet method:

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

While the values as a List can be obtained creating a new ArrayList from a Collection returned by the Map.values method:

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

The result of getting the List of keys:

Apple
Another
Hello

The result of getting the List of values:

3.14
Element
World
coobird
  • 159,216
  • 35
  • 211
  • 226
  • 5
    It should be noted that the order of values returned by those methods is *not defined* and for `HashMap` and similar un-sorted `Map` implementations it will be effectively random. – Joachim Sauer Mar 30 '11 at 08:02
  • 2
    Yes, you would have to know it is a LinkedHashMap or something of that sort. The problem with the original question is that the question is misstated, that is it needs editing. The question is not to convert a Map to a List, but rather how to get the values of the map as a List. The method values gives you a Collection, but not a list, and hence the need for a neat little trick. – demongolem Feb 11 '12 at 19:47
  • I think you could add to your answer what @M0les says: That you would need to "go via" SortedMap somehow. Either start with a concrete SortedMap implementation (Such as TreeMap) or insert your input Map into a SortedMap before converting that to List – Ignacio Rubio Nov 17 '14 at 16:33
65

Using the Java 8 Streams API.

List<Value> values = map.values().stream().collect(Collectors.toList());
Matej Kormuth
  • 2,139
  • 3
  • 35
  • 52
  • 12
    I prefer the accepted, constructor-based answer. Streams should be for simplifying code. – RavenMan Feb 24 '17 at 11:15
  • 1
    @Aaron Yes, for the task of getting a List of values from Map the constructor seems to be simplier. However if you are using Streams extensivly in a codebase it's better to stay consistent. – Matej Kormuth Feb 24 '17 at 13:57
  • 1
    when i use this get an error if I am fetching huge amount of data ..thread is looping on java.util.stream.ReduceOps$3.makeSink(Unknown Source). If threads loop infinitely, CPU consumption will start to spike up. Looping threads stack trace are given below, examine it – Ganesh Giri Aug 23 '19 at 05:51
  • I also like this code, but IntelliJ IDE suggests to change the code like this: ```java List values = new ArrayList<>(map.values()); ``` – pincoin Nov 26 '22 at 14:16
29

map.entrySet() gives you a collection of Map.Entry objects containing both key and value. you can then transform this into any collection object you like, such as new ArrayList(map.entrySet());

java dude
  • 291
  • 3
  • 2
26

a list of what ?

Assuming map is your instance of Map

  • map.values() will return a Collection containing all of the map's values.
  • map.keySet() will return a Set containing all of the map's keys.
aberrant80
  • 12,815
  • 8
  • 45
  • 68
Diego Amicabile
  • 579
  • 4
  • 12
15

I guess you want to convert the values contained in the Map to a list? Easiest is to call the values() method of the Map interface. This will return the Collection of value objects contained in the Map.

Note that this Collection is backed by the Map object and any changes to the Map object will reflect here. So if you want a separate copy not bound to your Map object, simply create a new List object like an ArrayList passing the value Collection as below.

ArrayList<String> list = new ArrayList<String>(map.values());
maneesh
  • 1,092
  • 1
  • 8
  • 11
8
    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);

we can have both key and value pair in list.Also can get key and value using Map.Entry by iterating over list.

user11
  • 197
  • 2
  • 8
6

If you want to ensure the values in the resultant List<Value> are in the key-ordering of the input Map<Key, Value>, you need to "go via" SortedMap somehow.

Either start with a concrete SortedMap implementation (Such as TreeMap) or insert your input Map into a SortedMap before converting that to List. e.g.:

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

Otherwise you'll get whatever native ordering the Map implementation provides, which can often be something other than the natural key ordering (Try Hashtable or ConcurrentHashMap, for variety).

M0les
  • 111
  • 1
  • 5
5
// 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,287
  • 12
  • 12
4
 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());
 }
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
1
public List<Object> convertMapToList(Map<Object, Object> map){
return new ArrayList<>(map.values());
}
1

Here's the generic method to get values from map.

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;
}
Hearaman
  • 8,466
  • 13
  • 41
  • 58
  • You have to initialize ArrayList with the size of Map, if you have a map got like 1 Million records, good luck with having .add() dealing with resizing the array over and over again. – Al-Mothafar Nov 07 '22 at 14:40
1

If you want an immutable copy of the values:

List<Value> list = List.copyOf(map.values())
Stefan Haberl
  • 9,812
  • 7
  • 72
  • 81