Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SparseIntArray instead of HashMap <Integer, Integer> with putSerializable

Tags:

java

android

When I use a HashMap with an Integer key and data values in Android I get this message in Eclipse:

Use new SparseIntArray(...) for better performance

Now the problem is that SparseIntArray() doesn't implement the Serializable interface and can't be used with getSerializable() and putSerializable() in onRestoreInstanceState().

  1. How important is using SparseIntArray() instead of the HashMap<Integer, Integer>?

  2. Should I go through the trouble of making SparseIntArray serializable? (My first idea is making a wrapper class that implements Serializable, is this the right way to go?)

like image 666
VM4 Avatar asked Jun 13 '13 02:06

VM4


People also ask

Can we use integer as key in HashMap?

It can store different types: Integer keys and String values or same types: Integer keys and Integer values. HashMap is similar to HashTable, but it is unsynchronized. It is allowed to store null keys as well, but there can only be one null key and there can be any number of null values.

Can we use primitives as key in HashMap?

The keys and values of a map can be any reference type. We can't use primitive types because of a restriction around the way generics were designed. A HashMap allows one null key and multiple null values. It doesn't preserve the order of the elements and doesn't guarantee the order will remain the same over time.

Can we use int in map?

int is a primitive data type. It only defines that the value is an integer in binary form. It has no inherent methods or fields that you can call. It is not an object and can not be used in an Object reference.

What is SparseIntArray?

Public constructors SparseIntArray() Creates a new SparseIntArray containing no mappings. SparseIntArray(int initialCapacity) Creates a new SparseIntArray containing no mappings that will not require any additional memory allocation to store the specified number of mappings.


2 Answers

1) How important is using SparseIntArray instead of the HashMap ?

It depends on how you are using it. But unless you are trying to represent many and/or large "arrays" like this, the difference is unlikely to be significant.

Note that Java SE doesn't have any sparse array classes, and it is not normally an issue.

2) Should I go through the trouble of making SparseIntArray serializable? (My first idea is making a wrapper class that implements Serializable, is this the right way to go?)

See above, and below.

Implementing a wrapper sounds reasonable ... if you need to go to this trouble. Another approach might be to declare a serializable subclass of SparseIntArray. It would be advisable to declare custom readObject and writeObject methods.


The SparseIntArray class (source code) uses a pair of int arrays to represent the keys and values in the mapping, and uses binary search to do the lookup. The keys are kept in order with no "holes" and lookup is performed using binary search. This means the following:

  • Memory usage for a SparseIntArray will be roughly a factor of 10 less that for an equivalent HashMap. This is due to a combination of things:

    • the hash table array holds roughly 1 reference per entry (depending on how full the table is ...),

    • the keys and values have to be "boxed" as Integer objects in a HashMap, and

    • each entry in a HashMap requires a "node" object that is fairly heavy weight - 4 fields in the standard implementation.

    (However, if you create the Integer objects the right way, the "boxing" overhead can be mitigated by the effects of the Integer classes instance cache.)

    By contrast, the sparse version requires 2 * capacity 4 byte words.

  • Lookup (i.e. get) is O(logN) compared with O(1) for a HashMap.

  • Random insertion is O(N) compared with O(1) for a HashMap. (This is because an insertion has to move on average half of the existing entries so that the new entry can be added at the correct position in the arrays.)

  • Sequential insertion (i.e. in ascending in key order) is O(1).

So "which is best" clearly depends on what you are optimizing for, how you use the data structure, and how big it is going to get.

like image 121
Stephen C Avatar answered Oct 26 '22 22:10

Stephen C


The problem with using a HashMap<Integer, Integer> is that every key and value needs to be boxed. The impact of this can range from nothing to being a heavy load on the system from huge amounts of garbage generation and/or memory use (not to mention the slight performance penalty of boxing/unboxing values). (These concerns have also driven the development of several third-party collection frameworks for primitives.)

If you decide that the benefits of SparseIntArray are worth having, then I think your approach of a wrapper class is reasonable. An alternative would be to make it implement Parcelable, which can also be used to save/restore the instance state.

like image 36
Ted Hopp Avatar answered Oct 26 '22 21:10

Ted Hopp