Подтвердить что ты не робот

Почему значения HashMap не отображаются в списке?

Я помещаю значения в 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.lang.ClassCastException:
java.util.HashMap $Значения не могут быть добавлены в java.util.List

Но это позволяет мне передать его при создании списка:

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

Ответ 1

TL; DR

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

Объяснение

Потому что HashMap#values() возвращает 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 #(): Проверьте тип возврата в источнике и спросите себя, может ли java.util.Collection быть переведено в java.util.ArrayList? Нет

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

ArrayList (Collection): Проверьте тип аргумента в источнике. Может ли метод, аргумент которого является супер-типом, принимает подтип? Да

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

Ответ 2

Ответ можно найти, прочитав JavaDoc

Метод 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 имеет конструктор, который принимает коллекцию.

Ответ 3

Это потому, что values() возвращает Collection, который в соответствии с исходным кодом HashMap имеет тип AbstractCollection и поэтому не может быть отброшен в List.

Вы можете создать экземпляр ArrayList, передав его values() result, потому что конструктор ArrayList может принимать Collection в качестве своего аргумента.

Ответ 4

Если вы уже создали экземпляр своего подтипа List (например, ArrayList, LinkedList), вы можете использовать метод addAll.

например.

valuesToMatch.addAll(myCollection)

Многие подтипы списка также могут брать исходный набор в свой конструктор.

Ответ 5

Вы проверяете API, что возвращается методом values()? И что ArrayList конструктор принимает?

Ответ 6

У меня возникла одна и та же проблема. Но потом я понял, что values ​​() возвращает Collection, а не List. Но мы можем создать экземпляр нового ArrayList следующим образом:

Список значенийToMatch = new ArrayList (highLowValueMap.values ​​());

Поскольку ArrayList имеет конструктор, который может принимать в качестве аргумента Collection.

Ответ 7

Хорошо, потому что ваши ценности действительно HashSet. Вы можете написать код, подобный этому, для перебора по набору:

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

Ответ 8

Values является внутренним классом класса HashMap (см. символ $в java.util.HashMap$Values).
 Метод HashMap.values ​​() возвращает объект класса Values, который не реализует интерфейс List. Так что ClassCastException.
Вот внутренний закрытый Values закрытый класс в HashMap, который не реализует интерфейс List. Даже AbstractCollection также не реализует интерфейс List.
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. Теперь какой класс реализует этот интерфейс 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

Ответ 9

Я сомневаюсь в избранном лучшем ответе, где говорится: "Поскольку значения HashMap #() возвращают java.util.Collection, и вы не можете отбросить коллекцию в ArrayList, таким образом вы получите ClassCastException."

Не потому, что Collection не может быть передан в ArrayList, настоящая причина в том, что коллекция, возвращаемая HashMap.values ​​(), создается внутренним классом HashMap.Values. И HashMap.Values ​​не является суперклассом ArrayList.