为什么HashMap值不在List中转换?

我正在把值放到这个forms的hashmap中,

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

我想通过使用map的values()方法来创build一个列表。

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

要么

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

但是,它会抛出一个exception:

线程“main”中的exceptionjava.lang.ClassCastException:
java.util.HashMap $ Values不能转换为java.util.List

但它允许我将它传递给创build一个列表:

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

TL; DR

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

说明

因为HashMap#values()返回一个java.util.Collection<V>并且你不能将一个Collection转换成一个ArrayList ,所以你得到了ClassCastException

我build议使用ArrayList(Collection<? extends V>)构造函数。 这个构造函数接受一个实现了Collection<? extends V>的对象Collection<? extends V> Collection<? extends V>为一个参数。 当你像这样传递HashMap.values()的结果时,你将不会得到ClassCastException

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

深入研究Java API源代码

HashMap#values():检查源代码中的返回types,问问自己, java.util.Collection可以被转换成java.util.ArrayList ? 没有

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

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

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

答案可以通过阅读JavaDocfind

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有一个接受集合的构造函数。

这是因为values()返回根据HashMap源代码的CollectionAbstractCollectiontypes的Collection ,因此不能转换为List

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

如果您已经创build了List子types的实例(例如,ArrayList,LinkedList),那么可以使用addAll方法。

例如,

 valuesToMatch.addAll(myCollection) 

许多列表子types也可以在其构造函数中使用源集合。

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

我面临同样的问题,但后来我意识到values()返回集合,而不是一个列表。 但是我们可以像这样实例化一个新的ArrayList:

List valuesToMatch = new ArrayList(highLowValueMap.values());

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

那是因为你的值真的是一个HashSet。 你可以编写这样的代码遍历整个集合:

 List<Double> valuesToMatch=new ArrayList<>(); for(Double d : highLowValueMap.values(){ valuesToMatch.put(d); } 

ValuesHashMap类中的内部类(请参见java.util.HashMap$Values $ symbol)。
HashMap.values()方法将返回没有实现List接口的Values类的对象。 ClassCastException也是如此。
这是HashMap中的Values内部私有类,它不实现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()方法的返回types是Collection 。 现在哪个类正在实现这个Collection接口? Answer是HashMap类(内部类)内的Values类。 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 

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

这不是因为Collection不能被转换成ArrayList,真正的原因是由HashMap.values()返回的Collection由内部类HashMap.Values支持。 而HashMap.Values不是ArrayList的超类。