为什么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源代码的Collection是AbstractCollectiontypes的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); }
Values是HashMap类中的内部类(请参见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的超类。