почему значения HashMap не отображаются в списке?
я помещаю значения в хэш-карту, которая имеет форму,
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();
однако, он выдает исключение:
исключение в потоке" main " java.ленг.ClassCastException:
Ява.утиль.Значения HashMap$не могут быть приведены к java.утиль.Список
но это позволяет мне передать его в создание список:
List<Double> valuesToMatch = new ArrayList<Double>( highLowValueMap.values());
9 ответов:
TL; DR
List<V> al = new ArrayList<V>(hashMapVar.values());
объяснение
, потому что
HashMap#values()
возвращает ajava.util.Collection<V>
и вы не можете разыгратьCollection
наArrayList
, таким образом, вы получаетеClassCastException
.Я бы предложил использовать
ArrayList(Collection<? extends V>)
конструктор. Этот конструктор принимает объект, который реализуетCollection<? extends V>
в качестве аргумента. Вы не получитеClassCastException
когда вы передаете результатHashMap.values()
такой:List<V> al = new ArrayList<V>(hashMapVar.values());
Идем дальше в источник Java API код
HashMap#values (): Проверьте тип возврата в источнике и спросите себя, Может ли a
java.util.Collection
быть преобразован вjava.util.ArrayList
? Нетpublic Collection<V> values() { Collection<V> vs = values; return (vs != null ? vs : (values = new Values())); }
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); }
ответ можно найти, прочитав JavaDoc
The
values()
метод возвращает aCollection
так
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
передав ейvalues()
результат, потому чтоArrayList
конструктор может взятьCollection
в качестве аргумента.
Если вы уже создали экземпляр подтипа списка (например, ArrayList, LinkedList), вы можете использовать метод addAll.
например,
valuesToMatch.addAll(myCollection)
многие подтипы списка также могут принимать исходную коллекцию в своем конструкторе.
вы проверили API, что возвращается
values()
способ? А какой ArrayList конструктор можно?
Я столкнулся с той же проблемой, но потом я понял, что values() возвращает коллекцию, а не список. Но мы можем создать экземпляр нового ArrayList следующим образом:
List valuesToMatch = new ArrayList (highLowValueMap.значения());
потому что ArrayList имеет конструктор, который может принимать коллекцию в качестве аргумента.
Ну это потому, что ваши значения действительно хэш-набор. Вы можете написать такой код, чтобы перебирать набор:
List<Double> valuesToMatch=new ArrayList<>(); for(Double d : highLowValueMap.values(){ valuesToMatch.put(d); }
Values
внутренний классHashMap
класс (см. символ $ вjava.util.HashMap$Values
).
HashMap.values () метод вернетValues
объект класса, который не реализует . Так же как иClassCastException
.
Вот этоValues
внутренний частный класс в HashMap, который не реализует . Даже AbstractCollection также не реализует .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.
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
. Теперь какой класс реализует этот интерфейс коллекции ? Ответ:Values
класс, который находится внутри класса HashMap (внутренний класс). Возвращенное значение от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.утиль.Коллекция и вы не можете привести коллекцию в ArrayList, таким образом, вы получаете ClassCastException."
Это не потому, что коллекция не может быть приведена к ArrayList, реальная причина заключается в том, что коллекция возвращается HashMap.значения() опирается на внутреннее хранилище HashMap класса.Ценности. И HashMap.Значения это не супер класс коллекции ArrayList.