85

我将值放入形式为的哈希图中,

Map<Long, Double> highLowValueMap=new HashMap<Long, Double>();
highLowValueMap.put(1l, 10.0);
highLowValueMap.put(2l, 20.0);

我想通过使用values()地图的方法创建一个列表。

List<Double> valuesToMatch=new ArrayList<>();
valuesToMatch=(List<Double>) highLowValueMap.values();

或者

List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();

但是,它会引发异常:

线程“主”java.lang.ClassCastException 中的异常:
java.util.HashMap$Values 无法转换为 java.util.List

但它允许我将其传递给创建列表:

List<Double> valuesToMatch  = new ArrayList<Double>( highLowValueMap.values());
4

10 回答 10

150

TL;博士

List<V> al = new ArrayList<V>(hashMapVar.values());

解释

因为HashMap#values()返回 ajava.util.Collection<V>并且您不能将 aCollection转换为 a ArrayList,因此您得到ClassCastException.

我建议使用ArrayList(Collection<? extends V>)构造函数。Collection<? extends V>此构造函数接受一个作为参数实现的对象。ClassCastException当你通过这样的结果时你不会得到HashMap.values()

List<V> al = new ArrayList<V>(hashMapVar.values());

深入了解 Java API 源代码

HashMap#values():检查源代码中的返回类型,并问自己,可以将 ajava.util.Collection转换为java.util.ArrayList吗?不

public Collection<V> values() {
    Collection<V> vs = values;
    return (vs != null ? vs : (values = new Values()));
}

ArrayList(Collection):检查源中的参数类型。参数是超类型的方法可以接受子类型吗?是的

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}
于 2013-03-20T11:45:05.157 回答
25

阅读JavaDoc可以找到答案

values()方法返回一个Collection

所以

List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();

应该

Collection<Double> valuesToMatch= highLowValueMap.values();

您仍然可以像遍历列表一样遍历此集合。

http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html#values%28%29


这有效:

List<Double> valuesToMatch  = new ArrayList<Double>( highLowValueMap.values() );

因为ArrayList有一个接受集合的构造函数。

于 2013-03-20T11:45:31.627 回答
5

这是因为根据源代码values()返回的是类型,因此不能强制转换为.CollectionHashMapAbstractCollectionList

您可以实例化ArrayList传递它的values()结果,因为ArrayList构造函数可以Collection作为它的参数。

于 2013-03-20T11:45:40.997 回答
4

如果您已经创建了 List 子类型的实例(例如,ArrayList、LinkedList),您可以使用 addAll 方法。

例如,

valuesToMatch.addAll(myCollection)

许多列表子类型也可以在其构造函数中获取源集合。

于 2013-03-20T11:45:27.447 回答
2

你检查过API,values()方法返回什么?ArrayList构造函数接受什么?

于 2013-03-20T11:46:04.550 回答
2

我遇到了同样的问题,但后来我意识到 values() 返回 Collection,而不是 List。但是我们可以像这样实例化一个新的 ArrayList:

列出 valuesToMatch = new ArrayList(highLowValueMap.values());

因为 ArrayList 有一个可以将 Collection 作为其参数的构造函数。

于 2014-01-15T11:57:38.893 回答
1

嗯,这是因为你的值真的是一个 HashSet。您可以编写这样的代码来迭代集合:

List<Double> valuesToMatch=new ArrayList<>();
for(Double d : highLowValueMap.values(){
  valuesToMatch.put(d);
}
于 2013-03-20T11:45:08.077 回答
1

Values是类中的一个内部类HashMap(见 $ 符号java.util.HashMap$Values)。
HashMap.values() 方法将返回 Values未实现List接口的类对象。也是如此ClassCastException
这是ValuesHashMap 中的内部私有类,它没有实现List接口。甚至 AbstractCollection 也没有实现List接口。
AbstractCollection实现Collection接口。所以无法投射到List.

private final class Values extends AbstractCollection<V> {
        public Iterator<V> iterator() {
            return newValueIterator();
        }
        public int size() {
            return size;
        }
        public boolean contains(Object o) {
            return containsValue(o);
        }
        public void clear() {
            HashMap.this.clear();
        }
    }

更新

以下是 ArrayList 中的构造函数之一。

public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

所以hashmapObj.values()方法返回类型是Collection. 现在哪个类正在实现这个 Collection 接口?答案是ValuesHashMap 类(内部类)中的类。from 的返回值hashmapObj.values()可以传递给上面有效的 ArrayList 构造函数。

即使以下是有效的陈述。

HashMap<String, String> map  = new HashMap<String, String>();
Collection c = map.values();

但以下说法不正确

HashMap<String, String> map  = new HashMap<String, String>();
List c = map.values(); //compilation error.. return type is not List
于 2013-03-20T11:57:07.733 回答
1

我怀疑选择的最佳答案,它说:“因为 HashMap#values() 返回一个 java.util.Collection 并且你不能将 Collection 转换为 ArrayList,因此你会得到 ClassCastException。”

不是因为Collection不能强制转换为ArrayList,真正的原因是HashMap.values()返回的Collection是被内部类HashMap.Values备份的。而且 HashMap.Values 不是 ArrayList 的超类。

于 2017-05-04T15:52:34.357 回答
-1

要将 Map 实例中的值转换为列表,您可以使用Iterable<T>.map

val yourList: List<Any> = #Map.values.map { it }
于 2021-05-13T15:21:37.673 回答