如何在Java中将Map转换为List?

805

我如何将 Map<key,value> 转换为 List<value>?我应该遍历所有的 map 值并将它们插入到一个列表中吗?


1
我认为,如果必须将映射转换为列表,则这不是一个好的模型。应该以这样的方式编写代码,使得不会出现这种情况。 - Bugs Happen
13个回答

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

假设:

Map<Key,Value> map;

13
谢谢!我一直以为从Collection转换成List的转换会起作用。 - asgs
1
我怀疑它不起作用的原因是values()返回的集合取决于底层Map;而通过调用复制构造函数,您分配存储并将值复制到该存储中,从而断开连接... - Sheldon R.
4
如果我们有LinkedHashMap - 那么顺序会保持不变吗? - user2022068
1
@user2022068 是的,使用LinkedHashMap可以保留顺序。 - SusanW
2
@SheldonR。是的 - keySet()values() 返回的集合通常是提供底层结构的 Set 或 Collection 视图的 shim 对象(keySet() 返回 Set 是为了强调没有重复项)。对于 values(),返回的对象可能是一个 List,但通常不是。像你所说的创建一个真正的 List 会打破链接,这意味着你不再依赖原始 Map。然而,有时你只需要一个 List,因为某些 API 需要它 - 这强化了一个好的 API 应该尽可能地要求最抽象的接口的规则... - SusanW
显示剩余3条评论

144
这里的问题是 Map 有两个值(一个键和一个值),而 List 只有一个值(一个元素)。
因此,最好的方法是获取键或值的 List。(除非我们制作一个包装器来持有键/值对)。
假设我们有一个 Map
Map<String, String> m = new HashMap<String, String>();
m.put("Hello", "World");
m.put("Apple", "3.14");
m.put("Another", "Element");

通过从 Map.keySet 方法返回的 Set 创建一个新的 ArrayList,可以获得作为 List 的键:

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

虽然值可以作为List获得,但需要从Map.values方法返回的Collection创建一个新的ArrayList

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

获取键的List的结果:

苹果
另一个
你好

获取值的List的结果:

3.14
Element
World

5
需要注意的是,这些方法返回的值的顺序是未定义的,对于HashMap和类似的未排序的Map实现来说,它将是有效地随机的。 - Joachim Sauer
2
是的,您必须知道它是LinkedHashMap或那种类型的东西。原问题的问题在于问题陈述不正确,需要编辑。问题不是将Map转换为List,而是如何将映射的值作为List获取。方法values会给您一个集合,但不是列表,因此需要一个巧妙的小技巧。 - demongolem
我认为你可以在回答中加入@M0les的建议:你需要以某种方式“通过”SortedMap。可以从具体的SortedMap实现(例如TreeMap)开始,或者将输入Map插入到SortedMap中,然后再将其转换为List。 - Ignacio Rubio

65
使用Java 8的流API。
List<Value> values = map.values().stream().collect(Collectors.toList());

13
我更倾向于被广泛接受的基于构造函数的答案。流应该用于简化代码。 - RavenMan
1
@Aaron 是的,对于从 Map 中获取值列表的任务,构造函数似乎更简单。但是,如果您在代码库中广泛使用 Streams,则最好保持一致性。 - Matej Kormuth
1
当我使用此代码获取大量数据时,会出现错误,线程停留在java.util.stream.ReduceOps $ 3.makeSink(未知源)上。如果线程无限循环,则CPU利用率将开始急剧上升。以下是循环线程的堆栈跟踪,请检查。 - Ganesh Giri
我也喜欢这段代码,但IntelliJ IDE建议将代码更改为:List values = new ArrayList<>(map.values()); - pincoin

30

map.entrySet() 方法可以获取包含键值对的 Map.Entry 对象的集合,你可以将其转换为任何你喜欢的集合对象,例如 new ArrayList(map.entrySet());


26
  • map.values()将返回一个包含映射中所有值的集合Collection
  • map.keySet()将返回一个包含映射中所有键的Set

15

我猜你想把Map里的值转换成一个list?最简单的方法是调用Map接口的values()方法。这将返回包含在Map中的值对象的Collection

请注意,这个Collection是由Map对象支持的,对Map对象所做的任何更改都会反映在此处。因此,如果你想要一个与你的Map对象无关的独立副本,只需创建一个新的List对象,比如一个ArrayList,将值Collection传递如下。

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

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);

在列表中,我们可以拥有键和值对。同时,也可以通过遍历列表来使用Map.Entry获取键和值。


6
如果您想确保结果中的List<Value>值按照输入Map<Key, Value>的键排序,您需要以某种方式“通过”SortedMap进行操作。可以选择从具体的SortedMap实现(例如TreeMap)开始,或者在将输入Map转换为List之前将其插入到SortedMap中。例如:
Map<Key,Value> map;
List<Value> list = new ArrayList<Value>( new TreeMap<Key Value>( map ));

否则,您将获得 Map 实现提供的任何本地排序,这通常不是自然键排序(尝试 Hashtable ConcurrentHashMap ,以获取多样性)。

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());    
}

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());
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接