Java 为什么HashMap值不在列表中强制转换?
我把值放到hashmap中,它的形式是Java 为什么HashMap值不在列表中强制转换?,java,arraylist,collections,hashmap,Java,Arraylist,Collections,Hashmap,我把值放到hashmap中,它的形式是 Map<Long, Double> highLowValueMap=new HashMap<Long, Double>(); highLowValueMap.put(1l, 10.0); highLowValueMap.put(2l, 20.0); 或 List valueToMatch=(List)highLowValueMap.values(); 但是,它会引发一个异常: 线程“main”java.lang.ClassCas
Map<Long, Double> highLowValueMap=new HashMap<Long, Double>();
highLowValueMap.put(1l, 10.0);
highLowValueMap.put(2l, 20.0);
或
List valueToMatch=(List)highLowValueMap.values();
但是,它会引发一个异常:
线程“main”java.lang.ClassCastException中的异常:无法将java.util.HashMap$值转换为java.util.List 但它允许我将其传递给列表的创建:
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values());
List valuesToMatch=new ArrayList(highLowValueMap.values());
TL;博士
深入了解JavaAPI源代码
HashMap#values():检查源代码中的返回类型,并问问自己,java.util.Collection
是否可以强制转换为java.util.ArrayList
?没有
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
公共集合值(){
集合vs=值;
返回(vs!=null?vs:(value=newvalues());
}
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);
}
公共ArrayList(Collection)这是因为您的值实际上是一个HashSet。 您可以编写如下代码来迭代集合:
List<Double> valuesToMatch=new ArrayList<>();
for(Double d : highLowValueMap.values(){
valuesToMatch.put(d);
}
List valueToMatch=new ArrayList();
for(双d:highLowValueMap.values(){
值。放置(d);
}
如果已经创建了列表子类型的实例(例如ArrayList、LinkedList),则可以使用addAll方法
e、 g
许多列表子类型也可以在其构造函数中获取源集合。可以通过阅读JavaDoc找到答案
values()
方法返回一个集合
所以
List valueToMatch=(List)highLowValueMap.values();
应该是
Collection<Double> valuesToMatch= highLowValueMap.values();
Collection valueToMatch=highLowValueMap.values();
您仍然可以像遍历列表一样遍历此集合
这项工作:
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values() );
List valuesToMatch=new ArrayList(highLowValueMap.values());
因为ArrayList
有一个接受集合的构造函数。这是因为values()
返回collection
,根据HashMap
的源代码,它属于AbstractCollection
类型,因此不能强制转换到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
传递它的values()
结果,因为ArrayList
构造函数可以将Collection
作为其参数。是否检查了API、方法返回了什么?以及ArrayList接受了什么?values
是HashMap
类中的内部类(请参见java.util.HashMap$Values
中的$symbol)。HashMap.values()方法将返回未实现
List
接口的values
类的对象。ClassCastException
这是HashMap中的
值
内部私有类,它没有实现列表
接口。甚至AbstractCollection也没有实现列表
接口。AbstractCollection
实现了Collection
接口。因此无法强制转换到列表
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();
}
}
但以下说法是不正确的
HashMap<String, String> map = new HashMap<String, String>();
List c = map.values(); //compilation error.. return type is not List
HashMap map=newhashmap();
List c=map.values();//编译错误..返回类型不是List
我也面临同样的问题,但后来我意识到values()返回集合,而不是列表。
但我们可以实例化一个新的ArrayList,如下所示:
List ValueToMatch=new ArrayList(highLowValueMap.values())
因为ArrayList有一个构造函数,可以将Collection作为其参数。我怀疑所选的最佳答案,它说: “因为HashMap#values()返回java.util.Collection,而您不能将集合强制转换为ArrayList,因此您会得到ClassCastException。”
这并不是因为集合不能强制转换到ArrayList,真正的原因是HashMap.values()返回的集合由内部类HashMap.values.和HashMap.values备份,而不是ArrayList的超类。要将值从映射实例转换为列表,可以使用
Iterable.Map
val yourList: List<Any> = #Map.values.map { it }
val-yourList:List=#Map.values.Map{it}
values方法返回一个集合,而不是列表。不,values()
方法返回一个collection
和keySet()
返回一个集合
。您可以通过add而不是put将项目添加到ArrayList,这是Set。您的答案是最容易理解的。我不明白为什么我可以执行集合c=new ArrayList();
但不能强制转换值()
到该类型,甚至列表
@ashur这是因为这种方式可以将代码转换为接口,这是可以接受的。在您的示例中,您可以将集合更改为列表(因为它也是一个接口),但仍然可以,但不能转换为接口。
Collection<Double> valuesToMatch= highLowValueMap.values();
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values() );
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();
}
}
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);
}
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
val yourList: List<Any> = #Map.values.map { it }