HashMap и int в качестве ключа
Я пытаюсь построить HashMap, который будет иметь целое число в качестве ключей и объектов в качестве значений.
Мой синтаксис:
HashMap<int, myObject> myMap = new HashMap<int, myObject>();
Однако возвращаемая ошибка - Синтаксическая ошибка в токене "int", Размеры, ожидаемые после этого токена - Я не понимаю, почему я должен добавить измерение (т.е. сделать int в массив), поскольку мне нужно только сохранить цифру в качестве ключа.
Что я мог сделать?
Заранее спасибо!:)
13 ответов
Вы не можете использовать примитив, потому что HashMap использует объект для ключа внутри. Таким образом, вы можете использовать только объект, который наследуется от Object (это любой объект).
Это функция put() в HashMap, и, как вы можете видеть, она использует Object для K:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
Выражение "k = e.key" должно прояснить это.
Я предлагаю использовать обертку, такую как Integer и autoboxing.
Использование Integer
вместо.
HashMap<Integer, MyObject> myMap = new HashMap<Integer, MyObject>();
Java автоматически автоматически int
примитивные значения Integer
объекты.
Узнайте больше об автобоксировании из документации Oracle Java.
Для всех, кто кодирует Java для устройств Android и заканчивает здесь: используйте SparseArray для лучшей производительности
private final SparseArray<myObject> myMap = new SparseArray<myObject>();
с этим вы можете использовать Int вместо Integer, как
int newPos = 3;
myMap.put(newPos, newObject);
myMap.get(newPos);
Вы можете попробовать использовать Trove http://trove.starlight-systems.com/
TIntObjectHashMap, вероятно, то, что вы ищете.
HashMap не допускает примитивные типы данных в качестве аргументов. Он может принимать только объекты, так
HashMap<int, myObject> myMap = new HashMap<int, myObject>();
не будет работать.
Вы должны изменить декларацию на
HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();
так что даже когда вы делаете следующее
myMap.put(2,myObject);
Примитивный тип данных автоматически помещается в объект Integer.
8 (int) === boxing ===> 8 (Integer)
Вы можете прочитать больше об автобоксе здесь http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Для тех, кто заинтересован в такой карте, потому что вы хотите уменьшить объем автобокса в Java оберток над типами примитивов, я бы рекомендовал использовать коллекции Eclipse. Trove больше не поддерживается, и я считаю, что это довольно ненадежная библиотека (хотя она все равно довольно популярна), и ее нельзя сравнивать с коллекциями Eclipse.
import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;
public class Check {
public static void main(String[] args) {
IntObjectHashMap map = new IntObjectHashMap();
map.put(5,"It works");
map.put(6,"without");
map.put(7,"boxing!");
System.out.println(map.get(5));
System.out.println(map.get(6));
System.out.println(map.get(7));
}
}
В этом примере выше In tObjectHashMap.
Поскольку вам нужно сопоставление объектов int->, также рассмотрите возможность использованияYourObjectType[]
массив или List<YourObjectType>
и доступ к значениям по индексу, поскольку map по своей природе является ассоциативным массивом с типом int в качестве индекса.
Основная причина того, что HashMap не допускает использование примитива в качестве ключей, заключается в том, что HashMap разработан таким образом, что для сравнения ключей используется метод equals(), и метод можно вызывать только для объекта, а не для примитива.
Таким образом, когда int автоматически помещается в Integer, Hashmap может вызывать метод equals() для объекта Integer.
Вот почему вы должны использовать Integer вместо int. Я имею в виду, что hashmap выдает ошибку, указав в качестве ключа int (не знаю, что выдается за ошибка)
И если вы думаете, что вы можете повысить производительность Map, сделав примитив в качестве ключа, есть библиотека FastUtil, которая содержит реализацию Map с типом int в качестве ключа.
Из-за этого это намного быстрее, чем Hashmap
Если вы кодируете в Android, существует SparseArray, отображающий целое число на объект.
Если вы используете Netty и хотите использовать карту с примитивными ключами типа int, вы можете использовать ее IntObjectHashMap
Некоторые из причин использования коллекций примитивных типов:
- повысить производительность за счет специализированного кода
- уменьшить количество мусора, который может оказать давление на ГХ
Вопрос о специализированных и обобщенных коллекциях может создать или сломать программы с высокими требованиями к пропускной способности.
Используйте int как Object, а не как примитивный тип
HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();
Пожалуйста, используйте HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();
Я не понимаю, почему я должен добавить измерение (т.е. сделать int в массив), так как мне нужно только сохранить цифру в качестве ключа.
Массив также является объектом, поэтому HashMap<int[], MyObject>
является допустимой конструкцией, которая использует массивы int в качестве ключей.
Компилятор не знает, что вы хотите или что вам нужно, он просто видит языковую конструкцию, которая является почти правильной, и предупреждает, чего не хватает, чтобы она была полностью правильной.
Подобно тому, как список не принимает примитивные данные, карта не принимает примитивные типы данных в качестве ключа или значения. если мы попытаемся поместить примитивные типы данных в качестве пары ключ-значение, это сделает автоупаковку