wake-up-neo.net

warum werden HashMap-Werte nicht in die Liste aufgenommen?

Ich füge Werte in die Hashmap, die von der Form ist,

Map<Long, Double> highLowValueMap=new HashMap<Long, Double>();
highLowValueMap.put(1l, 10.0);
highLowValueMap.put(2l, 20.0);

Ich möchte eine Liste mit der values()-Methode der Map erstellen.

List<Double> valuesToMatch=new ArrayList<>();
valuesToMatch=(List<Double>) highLowValueMap.values();

oder 

List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();

Es gibt jedoch eine Ausnahme:

Ausnahme im Thread "main" Java.lang.ClassCastException:
Java.util.HashMap $ Werte können nicht in Java.util.List umgewandelt werden

Aber es erlaubt mir, es in die Erstellung einer Liste zu geben:

List<Double> valuesToMatch  = new ArrayList<Double>( highLowValueMap.values());
63
bNd

TL; DR

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

Erläuterung

Da HashMap#values() einen Java.util.Collection<V> zurückgibt und Sie keine Collection in eine ArrayList umwandeln können, erhalten Sie ClassCastException.

Ich würde vorschlagen, ArrayList(Collection<? extends V>) Konstruktor zu verwenden. Dieser Konstruktor akzeptiert ein Objekt, das Collection<? extends V> als Argument implementiert. Sie erhalten ClassCastException nicht, wenn Sie das Ergebnis von HashMap.values() folgendermaßen übergeben:

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

Weiter zum Java-API-Quellcode

HashMap # values ​​(): Überprüfen Sie den Rückgabetyp in der Quelle und fragen Sie sich, ob ein Java.util.Collection in Java.util.ArrayList umgewandelt werden kann. Nein

public Collection<V> values() {
    Collection<V> vs = values;
    return (vs != null ? vs : (values = new Values()));
}

ArrayList (Collection): Überprüfen Sie den Argumenttyp in der Quelle. Kann eine Methode, deren Argument ein Supertyp ist, einen Untertyp akzeptieren? Ja

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

Die Antwort kann durch Lesen des JavaDoc gefunden werden

Die values()-Methode gibt eine Collection zurück. 

So

List<Double> valuesToMatch=(List<Double>) highLowValueMap.values();

Sollte sein 

Collection<Double> valuesToMatch= highLowValueMap.values();

Sie können diese Sammlung immer noch wie eine Liste durchlaufen.

http://docs.Oracle.com/javase/6/docs/api/Java/util/HashMap.html#values%28%29


Das funktioniert: 

List<Double> valuesToMatch  = new ArrayList<Double>( highLowValueMap.values() );

Weil ArrayList einen Konstruktor hat, der eine Collection akzeptiert. 

21
cowls

Dies liegt daran, dass values()Collection zurückgibt, das laut Quellcode von HashMap vom Typ AbstractCollection ist und daher nicht in List umgewandelt werden kann.

Sie können ArrayList instantiieren, indem Sie das values()-Ergebnis übergeben, da der ArrayList-Konstruktor Collection als Argument verwenden kann.

5
Andrew Logvinov

Wenn Sie bereits eine Instanz Ihres List-Subtyps erstellt haben (z. B. ArrayList, LinkedList), können Sie die addAll-Methode verwenden.

z.B.,

valuesToMatch.addAll(myCollection)

Viele Listensubtypen können auch die Quellensammlung in ihren Konstruktor aufnehmen. 

3
user195488

Haben Sie die API überprüft, was von der values() -Methode zurückgegeben wird? Und was akzeptiert ArrayList constructor ?

2

Ich hatte das gleiche Problem, aber dann erkannte ich, dass die Werte () Collection und nicht eine Liste zurückgeben. Aber wir können eine neue ArrayList wie folgt instanziieren:

Liste valuesToMatch = new ArrayList (highLowValueMap.values ​​());

Weil ArrayList über einen Konstruktor verfügt, der Collection als Argument verwenden kann.

2

Nun, es liegt daran, dass Ihre Werte wirklich ein HashSet sind. Sie könnten einen Code wie folgt schreiben, um den Satz zu durchlaufen:

List<Double> valuesToMatch=new ArrayList<>();
for(Double d : highLowValueMap.values(){
  valuesToMatch.put(d);
}
1
Axarydax

Values ist eine innere Klasse in der HashMap-Klasse (siehe $ -Symbol in Java.util.HashMap$Values).
Die HashMap.values ​​() -Methode gibt das Objekt der Values-Klasse zurück, das keine List-Schnittstelle implementiert. So ist das ClassCastException
Hier ist die innere private Klasse Values in HashMap, die keine List-Schnittstelle implementiert. Auch AbstractCollection implementiert keine List-Schnittstelle.
AbstractCollection implementiert Collection-Schnittstelle. Also nicht in List umwandeln können.

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

Update

Das Folgende ist einer der Konstruktoren in 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);
    }

Der Rückgabetyp der hashmapObj.values()-Methode lautet Collection. Welche Klasse implementiert nun diese Collection-Schnittstelle? Die Antwort ist Values-Klasse, die sich innerhalb der HashMap-Klasse (innere Klasse) befindet. Der von hashmapObj.values() zurückgegebene Wert kann an den übergeordneten ArrayList-Konstruktor übergeben werden, der gültig ist.

Auch das Folgende ist gültig.

HashMap<String, String> map  = new HashMap<String, String>();
Collection c = map.values();

Die folgenden Aussagen sind jedoch falsch 

HashMap<String, String> map  = new HashMap<String, String>();
List c = map.values(); //compilation error.. return type is not List
1
AmitG

Ich bezweifle die ausgewählte beste Antwort: "" Da HashMap # values ​​() eine Java.util.Collection zurückgibt und Sie keine Collection in eine ArrayList umwandeln können, wird ClassCastException angezeigt.

Das liegt nicht daran, dass Collection nicht in ArrayList umgewandelt werden kann. Der wahre Grund ist, dass die von HashMap.values ​​() zurückgegebene Collection von der inneren Klasse HashMap.Values ​​gesichert wird. Und HashMap.Values ​​ist keine Superklasse von ArrayList.

0
Jin