次の形式のハッシュマップに値を入れています。
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());
List<V> al = new ArrayList<V>(hashMapVar.values());
HashMap#values()
はJava.util.Collection<V>
を返し、Collection
をArrayList
にキャストできないため、ClassCastException
を取得します。
ArrayList(Collection<? extends V>)
コンストラクターを使用することをお勧めします。このコンストラクターは、Collection<? extends V>
を実装するオブジェクトを引数として受け入れます。次のようにHashMap.values()
の結果を渡すと、ClassCastException
を取得できません。
List<V> al = new ArrayList<V>(hashMapVar.values());
HashMap#values():ソースの戻り値の型を確認し、自問してください。Java.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);
}
答えは、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
にはコレクションを受け入れるコンストラクターがあるためです。
values()
がCollection
を返すのは、HashMap
のソースコードによると、AbstractCollection
型であり、List
にキャストできないためです。
ArrayList
コンストラクターはその引数としてArrayList
を取ることができるため、Collection
を渡すことでvalues()
結果をインスタンス化できます。
Listサブタイプ(ArrayList、LinkedListなど)のインスタンスを既に作成している場合は、addAllメソッドを使用できます。
例えば。、
valuesToMatch.addAll(myCollection)
多くのリストサブタイプは、コンストラクターでソースコレクションを取ることもできます。
values()
メソッドが返すAPIを確認しましたか?そして、ArrayList constructor は何を受け入れますか?
同じ問題に直面しましたが、その後、values()はListではなくCollectionを返すことに気付きました。ただし、次のように新しいArrayListをインスタンス化できます。
リストの値ToMatch = 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
の$記号を参照)。
HashMap.values()メソッドは、Values
インターフェイスを実装していないList
クラスのオブジェクトを返します。 ClassCastException
も同様です。
これは、Values
インターフェイスを実装していないHashMapの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のコンストラクターの1つです。
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インターフェースを実装していますか?答えは、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を返すため、CollectionをArrayListにキャストできないため、ClassCastExceptionが発生するため、選択したベストアンサーを疑います。」
CollectionをArrayListにキャストできないからではありません。実際の理由は、HashMap.values()によって返されるCollectionが内部クラスHashMap.Valuesによってバックアップされるためです。また、HashMap.ValuesはArrayListのスーパークラスではありません。