HashMap和int作为键


104

我试图建立一个HashMap,它将具有整数作为键和对象作为值。

我的语法是:

HashMap<int, myObject> myMap = new HashMap<int, myObject>();

但是,返回的错误是-令牌“ int”的语法错误,此令牌后应包含尺寸-我不明白为什么应该添加尺寸(即:将int制成数组),因为我只需要存储一个数字作为关键。

我能做什么?

提前致谢!:)


14
HashMap不处理基元,仅处理对象。
Menno 2013年

与之相关的问题,但与int价值有关,而不是关键。
cyroxx

5
使用Integer代替。
2013年

将int自动装箱为Integer还是只将数据存储为String更好,这会更好吗?
Marcin Erbel

Answers:


25

您不能使用基元,因为HashMap在内部将对象用作键。因此,您只能使用从Object继承的对象(即任何对象)。

这就是HashMap中的put()函数,如您所见,它对K使用Object:

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”应明确说明。

我建议使用包装器,如整数和自动装箱。


137

使用Integer代替。

HashMap<Integer, MyObject> myMap = new HashMap<Integer, MyObject>();

Java会自动将int原始值自动装箱到Integer对象。

从Oracle Java文档中了解有关自动装箱的更多信息。


10
他也不宜命名类myObject
亚当根特

@AdamGent正确。所有类名都应以大写字母开头,我更正了推荐的代码。
gaborsch 2013年

3
我知道您知道:)我只想确保OP知道/学习。就我所知,他本可以在类型参数中放置一个变量名。
亚当·根特

1
请注意,最好使用ArrayMapSimpleArrayMap在Android上节省内存并提高性能(更多信息
Noah Huppert 2015年

42

对于为Android设备编写Java代码并最终到这里的每个人:使用SparseArray可获得更好的性能;

private final SparseArray<myObject> myMap = new SparseArray<myObject>();

这样,您可以使用int而不是Integer之类的方法;

int newPos = 3;

myMap.put(newPos, newObject);
myMap.get(newPos);

7
请记住,SparseArray比hashmap慢,但内存效率更高。因此,请勿在大型数据集上使用它。
TpoM6oH 2014年

SparseArray如何在速度较慢的情况下获得更好的性能?哪一个在我的Android游戏中使用

@Snake SparseArray如果像使用a那样分配一堆内存装箱和拆箱int HashMap,则vm需要尽快暂停执行以进行垃圾收集。如果您要尝试频繁且快速地执行某项操作,则这一点很重要。
2016年

1
请记住,插入的复杂度SparseArrayO(n)HashMap具有O(1))。当元素数量很大时,这一点很重要。插入这种数组的开头要慢得多。
弗拉基米尔·佩特拉科维奇

1
@ M.kazemAkhgary不完全是。put()开始时需要插入O(n)(而不是n log n),因为它会找到位置,然后移动所有后续元素。delete()本身确实需要O(log n),但是删除后的下一个插入或遍历元素将需要一个需要的垃圾收集O(n)
弗拉基米尔·佩特拉科维奇


4

HashMap不允许基元作为键的主要原因是HashMap的设计方式是,为了比较键,它使用equals()方法,并且只能在对象上而不是基元上调用方法。

因此,当将int自动装箱到Integer时,Hashmap可以在Integer对象上调用equals()方法。

因此,您应该使用Integer而不是int。我的意思是,在将int作为键时,hashmap会引发错误(不知道所引发的错误的含义)

如果您认为这样,则可以通过将基元作为键来提高Map性能,这是一个名为FastUtil的库,其中包含一个以int类型为键的Map实现。

因此,它比Hashmap快得多


1
不,不允许原始类型的主要原因是Java中的类型擦除,它在编译过程中实际上变成Map<Integer, String>Map<Object, Object>。顺便说一句,有IdentityHashMap使用==运算符进行相等性检查,但仍然不允许原始类型。
Yoory N.

3

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上阅读有关自动装箱的更多信息。



1

使用int作为对象而不是原始类型

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();

我已经写了HashMap <Integer,MyObject> myMap = new HashMap <Integer,MyObject>(); 但是显示使我的问题与>和<一起显示出很好的答案
franki3xe 2013年

我知道键入该命令很痛苦,但我正试图从即时状态中拯救您-1。在惩罚之前,我不像其他人那样发表评论(我没有-1你)。
亚当·根特

0

请用 HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();


0

我不明白为什么要添加一个维(即:将int制成数组),因为我只需要存储一个数字作为键。

数组也是一个对象,HashMap<int[], MyObject>使用int数组作为键的有效构造也是一个对象。

编译器不知道您想要什么或需要什么,它只会看到几乎正确的语言构造,并警告它完全正确所缺少的内容。


1
请注意,数组的哈希值与它的内容无关,因此具有相同内容的两个数组可以哈希为一个不同的值,从而使其成为非常差的键。
john16384 '18年

0

对于那些对这样的映射感兴趣的人,因为您希望减少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));
    }
}

在上面的示例中,IntObjectHashMap

当您需要int-> object映射时,还应考虑使用YourObjectType[]数组或List<YourObjectType>按索引访问值,因为map本质上是一个以int类型为索引的关联数组。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.