почему значения 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 59

9 ответов:

TL; DR

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

объяснение

, потому что HashMap#values() возвращает a java.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() метод возвращает a 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 передав ей 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.