web-dev-qa-db-fra.com

pourquoi les valeurs HashMap ne sont-elles pas exprimées dans la liste?

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());
63
bNd

TL; DR

List<V> al = new ArrayList<V>(hashMapVar.values());

Explication

É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());

Aller plus loin dans le code source de l'API Java

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);
}
110
PermGenError

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. 

21
cowls

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.

5
Andrew Logvinov

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. 

3
user195488

Avez-vous vérifié l'API, qu'est-ce qui est retourné par values() method? Et quel ArrayList constructeur accepte?

2

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.

2
Jyothirmayi Lalitha

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);
}
1
Axarydax

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
1
AmitG

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.

0
Jin