124

I am trying to build a HashMap which will have integer as keys and objects as values.

My syntax is:

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

However, the error returned is - Syntax error on token "int", Dimensions expected after this token - I don't understand why I should add a dimension (ie: making the int into an array) since I only need to store a digit as key.

What could I do?

starball
  • 20,030
  • 7
  • 43
  • 238
MrD
  • 4,986
  • 11
  • 48
  • 90
  • 19
    `HashMap` doesn't handle primitives, just objects. – Menno Apr 22 '13 at 13:41
  • 1
    [Related SO question](http://stackoverflow.com/questions/1780385/java-hashmapstring-int-not-working), but with `int` being the value, not the key. – cyroxx Apr 22 '13 at 13:44
  • 5
    Use `Integer` instead. – Hot Licks Apr 22 '13 at 16:57
  • Long story short, you must use an Integer - but you can add keys as if you it would allow you to use an int. Primitives aren't allowed, but the Integer class will handle primitive values assigned to the map. – FoxDonut Jul 08 '21 at 15:51

13 Answers13

154

Use Integer instead.

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

Java will automatically autobox your int primitive values to Integer objects.

Read more about autoboxing from Oracle Java documentations.

gaborsch
  • 15,408
  • 6
  • 37
  • 48
  • 11
    He should also not name a class `myObject` – Adam Gent Apr 22 '13 at 13:41
  • @AdamGent Correct. All class names should start with capitals, I corrected the recommended code. – gaborsch Apr 22 '13 at 13:43
  • 3
    I know you know :) I just want to make sure the OP knows/learns. For all I know he could have been putting a variable name in the type parameter. – Adam Gent Apr 22 '13 at 13:44
  • 2
    Just a quick little note, it is better to use `ArrayMap` or `SimpleArrayMap` on Android to save memory and increase performance([More information](https://medium.com/google-developers/developing-for-android-ii-bb9a51f8c8b9)) – Noah Huppert Jun 08 '15 at 21:06
48

For everybody who codes Java for Android devices and ends up here: use SparseArray for better performance;

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

with this you can use int instead of Integer like;

int newPos = 3;

myMap.put(newPos, newObject);
myMap.get(newPos);
Kerem
  • 11,377
  • 5
  • 59
  • 58
Stepoid
  • 521
  • 4
  • 9
  • 8
    Remember that SparseArray is slower than hashmap, but more memory efficient. So, don't use it on large data sets. – TpoM6oH Jun 17 '14 at 11:22
  • How is SparseArray used for better performance while it is slower? Which one to use in my android game – Snake Jan 09 '15 at 23:53
  • @Snake `SparseArray` If you allocate a bunch of memory boxing and unboxing ints as you would with a `HashMap`, the vm will need to pause execution for garbage collection sooner. This is important if you are trying to do something frequently and quickly. – Jon Jan 11 '16 at 22:25
  • 1
    Remember that complexity of insertion into `SparseArray` is **O(n)** (`HashMap` has **O(1)**). It is important when number of elements is large. Insertion into beginning of such array is much slower. – Vladimir Petrakovich Mar 04 '17 at 05:40
  • `SparseArray` "is generally slower than a traditional `HashMap`, since lookups require a binary search and adds and removes require inserting and deleting entries in the array". @Snake refer to https://developer.android.com/reference/android/util/SparseArray.html and https://stackoverflow.com/questions/25560629/sparsearray-vs-hashmap – TT-- Nov 26 '17 at 18:39
  • @VladimirPetrakovich inserting to end of `SparseArray` is `O(1)` if you use `append` (only usable when keys are added in increasing order), if you use `put` it takes `O(log n)` best case (insert at end) and `O(n log n)` worst case (insert at start). also `delete` will take `O(log n)` time because it will only mark found entries as deleted instead of actually deleting them until gc occurs (when you try to read items) – M.kazem Akhgary Dec 11 '18 at 06:16
  • 1
    @M.kazemAkhgary Not exactly. `put()` takes `O(n)` (not `n log n`) for insertion at start because it finds position and then shifts all following elements. `delete()` itself indeed takes `O(log n)`, but the next insertion or iterating through elements after delete will require a garbage collection that takes `O(n)`. – Vladimir Petrakovich Dec 12 '18 at 08:10
31

You can't use a primitive because HashMap use object internally for the key. So you can only use an object that inherits from Object (that is any object).

That is the function put() in HashMap and as you can see it uses Object for 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;
}

The expression "k = e.key" should make it clear.

I suggest to use a wrapper like Integer and autoboxing.

user1883212
  • 7,539
  • 11
  • 46
  • 82
6

HashMap does not allow primitive data types as arguments. It can only accept objects so

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

will not work.

You have to change the declaration to

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

so even when you do the following

myMap.put(2,myObject);

The primitive data type is autoboxed to an Integer object.

8 (int) === boxing ===> 8 (Integer)

You can read more on autoboxing here http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

Lakshmi
  • 2,204
  • 3
  • 29
  • 49
6

You may try to use Trove http://trove.starlight-systems.com/
TIntObjectHashMap is probably what you are looking for.

Arek
  • 489
  • 4
  • 7
5

For somebody who is interested in a such map because you want to reduce footprint of autoboxing in Java of wrappers over primitives types, I would recommend to use Eclipse collections. Trove isn't supported anymore, and I believe it is quite unreliable library in this sense (though it is quite popular anyway) and couldn't be compared with Eclipse collections.

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 this example above IntObjectHashMap.

As you need int->object mapping, also consider usage of YourObjectType[] array or List<YourObjectType> and access values by index (as map is, by nature, an associative array).

Alex
  • 3,923
  • 3
  • 25
  • 43
  • I'm considering using Trove - why do you believe it is unreliable? – Evgeniy Berezovsky Dec 10 '20 at 22:33
  • 1
    When I tried to find the best library related to the given problem, I had come across on some articles about trove's bugs and as this isn't supported anymore, I decided to not use it. But now, meeting more and more people using it in very big companies, I wouldn't consider it as a such bad choice, as it naturally tested so to say (also taking into account that I cannot find those articles about bugs now), but my self would rather use Eclipse collections. – Alex Dec 12 '20 at 00:46
  • I see. In the meantime, I have found (and added as an [answer](https://stackoverflow.com/a/65243513/709537)) the primitive collections included in the Netty library – Evgeniy Berezovsky Dec 12 '20 at 07:01
4

If you code in Android, there is SparseArray, mapping integer to object.

alvinsj
  • 875
  • 11
  • 15
4

The main reason with HashMap not allowing primitive as keys is that HashMap is designed in such a way that for comparing the keys, it makes use of equals() method, and a method can be called only on an object not on a primitive.

Thus when int is autoboxed to Integer, Hashmap can call equals() method on Integer object.

That is why, you should use Integer instead of int. I mean hashmap throws an error while putting int as a key (Don't know the meaning of the error that is thrown)

And if you think that, you can make Map performance faster by making a primitive as a key, there is a library called FastUtil which contains a Map implementation with int type as a key.

Because of this, it is much faster than Hashmap

FatherMathew
  • 960
  • 12
  • 15
  • 3
    No, the main reason for not allowing primitive types is [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) in Java, that effectively turns `Map` into `Map` during compilation. BTW, there is IdentityHashMap that uses `==` operator for equality check, that still doesn't allow primitive types. – Yoory N. Dec 05 '17 at 06:07
3

use int as Object not as primitive type

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();
franki3xe
  • 330
  • 1
  • 2
  • 17
  • I have writen HashMap myMap = new HashMap(); but displaying make my problem with > and < to display good answer – franki3xe Apr 22 '13 at 13:48
  • I know its painful to type but I was trying to save you from immediate `-1`. I unlike others comment before penalizing (I did not -1 you). – Adam Gent Apr 22 '13 at 13:51
2

If you are using Netty and want to use a map with primitive int type keys, you can use its IntObjectHashMap

Some of the reasons to use primitive type collections:

  • improve performance by having specialized code
  • reduce garbage that can put pressure on the GC

The question of specialized vs generalized collections can make or break programs with high throughput requirements.

Evgeniy Berezovsky
  • 18,571
  • 13
  • 82
  • 156
1

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

Michael
  • 10,063
  • 18
  • 65
  • 104
1

I don't understand why I should add a dimension (ie: making the int into an array) since I only need to store a digit as key.

An array is also an Object, so HashMap<int[], MyObject> is a valid construct that uses int arrays as keys.

Compiler doesn't know what you want or what you need, it just sees a language construct that is almost correct, and warns what's missing for it to be fully correct.

Yoory N.
  • 4,881
  • 4
  • 23
  • 28
  • 2
    Be careful with this, the hash value of an array is not related to its contents, so two arrays with the same content can hash to a different value making it a very poor key. – john16384 Jan 28 '18 at 13:05
1

Just like the list doesn't take the primitive data, map doesn't take the primitive data types as key or value. if we try to put primitive data types as the key value pair it will do the autoboxing

Suman
  • 11
  • 2
  • 2
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Reza Heidari Apr 17 '22 at 07:02