Je mets des valeurs dans le hashmap qui est de la forme,
Map<Long, Double> highLowValueMap=new HashMap<Long, Double>();
highLowValueMap.put(1l, 10.0);
highLowValueMap.put(2l, 20.0);
Je veux créer une liste en utilisant la méthode values()
de la carte.
List<Double> valuesToMatch=new ArrayList<>();
valuesToMatch=(List<Double>) highLowValueMap.values();
ou
List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();
Cependant, il lève une exception:
Exception dans le fil "principal" Java.lang.ClassCastException:
Java.util.HashMap $ Les valeurs ne peuvent pas être converties en Java.util.List
Mais cela me permet de passer à la création d'une liste:
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values());
List<V> al = new ArrayList<V>(hashMapVar.values());
Étant donné que HashMap#values()
renvoie un Java.util.Collection<V>
et que vous ne pouvez pas convertir une Collection
dans une ArrayList
, vous obtenez donc ClassCastException
.
Je suggère d'utiliser le constructeur ArrayList(Collection<? extends V>)
. Ce constructeur accepte un objet qui implémente Collection<? extends V>
en tant qu'argument. Vous n'obtiendrez pas ClassCastException
lorsque vous passerez le résultat de HashMap.values()
comme ceci:
List<V> al = new ArrayList<V>(hashMapVar.values());
HashMap # values (): Vérifiez le type de retour dans le source et demandez-vous si un Java.util.Collection
peut être converti en Java.util.ArrayList
? Non
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
ArrayList (Collection): Vérifiez le type d'argument dans la source. Une méthode dont l'argument est un super type peut-elle accepter un sous-type? Oui
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);
}
La réponse peut être trouvée en lisant le JavaDoc
La méthode values()
retourne une Collection
Alors
List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();
Devrait être
Collection<Double> valuesToMatch= highLowValueMap.values();
Vous pouvez toujours parcourir cette collection comme une liste.
http://docs.Oracle.com/javase/6/docs/api/Java/util/HashMap.html#values%28%29
Cela marche:
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values() );
Parce que ArrayList
a un constructeur qui accepte une collection.
C'est parce que values()
renvoie Collection
qui, selon le code source de HashMap
, est de type AbstractCollection
et ne peut donc pas être converti en List
.
Vous êtes en mesure d'instancier ArrayList
en lui passant le résultat values()
car le constructeur ArrayList
peut prendre Collection
comme argument.
Si vous avez déjà créé une instance de votre sous-type de liste (par exemple, ArrayList, LinkedList), vous pouvez utiliser la méthode addAll.
par exemple.,
valuesToMatch.addAll(myCollection)
De nombreux sous-types de liste peuvent également prendre la collection source dans leur constructeur.
Avez-vous vérifié l'API, qu'est-ce qui est retourné par values()
method? Et quel ArrayList constructeur accepte?
J'ai fait face au même problème, mais j'ai ensuite réalisé que values () retournait une collection, et non une liste .
Liste valuesToMatch = new ArrayList (highLowValueMap.values ());
Parce qu'ArrayList a un constructeur qui peut prendre Collection comme argument.
Eh bien, c'est parce que vos valeurs sont vraiment un HashSet. Vous pourriez écrire un code comme celui-ci pour parcourir l'ensemble:
List<Double> valuesToMatch=new ArrayList<>();
for(Double d : highLowValueMap.values(){
valuesToMatch.put(d);
}
Values
est une classe interne dans la classe HashMap
(voir $ symbol dans Java.util.HashMap$Values
).
La méthode HashMap.values () retournera l'objet de la classe Values
qui n'implémente pas l'interface List
. Alors est la ClassCastException
.
Voici la classe privée intérieure Values
dans HashMap qui n'implémente pas l'interface List
. Même AbstractCollection n'implémente pas non plus l'interface List
.AbstractCollection
implémente l'interface Collection
. Donc, pas capable de lancer à 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();
}
}
Mettre à jour
Voici l'un des constructeurs de 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);
}
Donc, le type de retour de la méthode hashmapObj.values()
est Collection
. Maintenant, quelle classe implémente cette interface Collection? La réponse est la classe Values
qui fait partie de la classe HashMap (classe interne). La valeur renvoyée par hashmapObj.values()
peut être transmise au constructeur ArrayList ci-dessus, qui est valide.
Même suivre des déclarations valables.
HashMap<String, String> map = new HashMap<String, String>();
Collection c = map.values();
Mais les déclarations suivantes sont incorrectes
HashMap<String, String> map = new HashMap<String, String>();
List c = map.values(); //compilation error.. return type is not List
Je doute de la meilleure réponse choisie, où il est écrit: "Parce que HashMap # values () renvoie un Java.util.Collection et que vous ne pouvez pas transtyper une Collection dans un ArrayList, vous obtenez donc ClassCastException."
Ce n'est pas parce que Collection ne peut pas être convertie en ArrayList, la vraie raison est que la Collection renvoyée par HashMap.values () est sauvegardée par la classe interne HashMap.Values. Et HashMap.Values n'est pas une super classe de ArrayList.