为什么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
是AbstractCollection
types的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的超类。