Ticker

6/recent/ticker-posts

Ad Code

Responsive Advertisement

In Java What is a Difference Between IdentityHashMap and HashMap + Performance Comparison

difference-between-identityhashmap-and-hashmap-performance-comparison

Sometime back I have a special case in which I have to compare Map’s Key based on equality operator (==).  The equality operator (==) compares the references (addresses in memory) of the two Keys as two different numbers.

In other hand, HashMap is most used Java Collection Framework component which compares uniqueness of the Key with the help of equals() method.

Also, IdentityHashMap does not use hash from object.hashCode() but uses System.identityHashCode(object). We could use IdentityHashMap for mutable objects for whose hash code changes during the runtime.

If you want to learn more on equals() and == which applies on String Object then follow this tutorial: https://crunchify.com/how-to-override-equals-and-hashcode-method-in-java/.

Basic Test which demonstrate above equals() and == behavior:

package crunchify.com.tutorials;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * @author Crunchify.com
 *
 */

public class CrunchifyIdenityHashMapVsHashMapSample {

        public static void main(String[] args) {
                Map<String, String> crunchifyIdentityHashMap = new IdentityHashMap<String, String>();
                Map<String, String> crunchifyHashMap = new HashMap<String, String>();

                // Let's checkout what happens when we put Unique Key to IdentityHashMap
                crunchifyIdentityHashMap.put("Company", "Crunchify");
                // this considered different object for == operator
                crunchifyIdentityHashMap.put(new String("Company"), "Google");
                crunchifyIdentityHashMap.put("Company", "Facebook");
                System.out.println("crunchifyIdentityHashMap KeySet Size: " + crunchifyIdentityHashMap.keySet().size());

                // Let's checkout what happens when we put Unique Key to HashMap
                crunchifyHashMap.put("Company", "Crunchify");
                // key1.equals(key2) returns true hence it removes the old value
                crunchifyHashMap.put(new String("Company"), "Google");
                crunchifyHashMap.put("Company", "Facebook");
                System.out.println("crunchifyHashMap KeySet Size: " + crunchifyHashMap.keySet().size());
        }
}

Result:

crunchifyIdentityHashMap KeySet Size: 2
crunchifyHashMap KeySet Size: 1

Let’s do Performance Testing on both Maps:

  1. Create Java Class: CrunchifyIdentityHashMapVsHashMapPerformance.java
  2. startCrunchifyTest()
    • Generates Random Map size in millions
    • Instantiate and Initialize crunchifyString[] String Array object with above generated Random Number with text: This is Crunchify's Test # number
  3. crunchifyCompareIdentityHashMapVsHashMap(String[] crunchifyString, Map<String, Integer> crunchifyMap, String name)
    • Pass all required parameters to this method
    • crunchifyMap will have value IdentityHashMap / HashMap
    • Iterate through crunchifyString[] and put values to Map  — this operation takes some time
    • Iterate through crunchifyString[] and get values from Map  — this operation takes some time
    • We will find out the execution time for both above operation so we could compare which one is better for above operations? IdentityHashMap OR HashMap
    • Print above result
  4. Perform above tasks 2 and 3 total 8 times.
package crunchify.com.tutorials;

import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Random;

/**
 * @author Crunchify.com
 *
 */

public class CrunchifyIdentityHashMapVsHashMapPerformance {
        static Random rand = new Random();

        private static void startCrunchifyTest() {

                // Let's run test for 5 times
                for (int i = 0; i < 15; ++i) {

                        // Let's create random Map size which we will use in IdentityHashMap and HashMap
                        int randomMapSize = 1000000 + rand.nextInt(9000000);
                        String[] crunchifyString = new String[randomMapSize];
                        for (int j = 0; j < randomMapSize; ++j)
                                // Assign below string to crunchifyString Object
                                crunchifyString[j] = "This is Crunchify's Test #" + j;

                        System.out.println("\nIteration # " + i + " - Creating String with size: " + randomMapSize);
                        crunchifyCompareIdentityHashMapVsHashMap(crunchifyString, new HashMap<String, Integer>(randomMapSize), "HashMap");

                        // Runs the garbage collector
                        System.gc();
                        crunchifyCompareIdentityHashMapVsHashMap(crunchifyString, new IdentityHashMap<String, Integer>(randomMapSize),
                                        "IdentityHashMap");

                        // Runs the garbage collector
                        System.gc();
                }
        }

        /**
         * @param crunchifyString
         * @param crunchifyMap
         *            : IdentityHashMap / HashMap
         * @param name
         */
        private static void crunchifyCompareIdentityHashMapVsHashMap(String[] crunchifyString, Map<String, Integer> crunchifyMap,
                        String name) {
                long start = System.currentTimeMillis();

                // put crunchifyString String[] to map
                for (int put = 0; put < crunchifyString.length; ++put)
                        crunchifyMap.put(crunchifyString[put], put);

                boolean result = false;
                for (int get = 0; get < crunchifyString.length; ++get) {
                        if (crunchifyMap.get(crunchifyString[get]) != get)
                                result = true;
                }
                System.out.println(name + " time taken : \t" + (System.currentTimeMillis() - start) / 1000. + " sec");

                // Check for result discrepancy
                if (crunchifyMap.size() != crunchifyString.length)
                        System.out.println("Please check size. Test failed");
                if (result)
                        System.out.println("Result failed..");
        }

        public static void main(String[] args) {
                System.out.println("IdentityHashMap Vs. HashMap comparison Test started...");

                // method to compare IdentityHashMap and HashMap
                startCrunchifyTest();
        }

}

Result:

IdentityHashMap Vs. HashMap comparison Test started...

Iteration # 0 - Creating String with size: 6964175
HashMap time taken :    3.155 sec
IdentityHashMap time taken :    1.517 sec

Iteration # 1 - Creating String with size: 6556459
HashMap time taken :    3.415 sec
IdentityHashMap time taken :    1.466 sec    <== IdentityHashMap gives better result for large object

Iteration # 2 - Creating String with size: 9567664
HashMap time taken :    4.173 sec
IdentityHashMap time taken :    2.339 sec    <== better

Iteration # 3 - Creating String with size: 4230755
HashMap time taken :    0.372 sec
IdentityHashMap time taken :    0.911 sec

Iteration # 4 - Creating String with size: 7821718
HashMap time taken :    1.096 sec
IdentityHashMap time taken :    0.812 sec

Iteration # 5 - Creating String with size: 8125421
HashMap time taken :    4.883 sec
IdentityHashMap time taken :    1.876 sec    <== better

Iteration # 6 - Creating String with size: 3166432
HashMap time taken :    0.537 sec
IdentityHashMap time taken :    0.708 sec

Iteration # 7 - Creating String with size: 2821415
HashMap time taken :    0.227 sec
IdentityHashMap time taken :    0.621 sec

Observation:

As you can see here in result, for large maps IdentityHashMap performs much better. Why? IdentityHashMap doesn't use equals() and hashcode() methods, which are considered very costly.

Just FYI:

Above operations which we are doing for putting and getting values from and into Map are very CPU intensive.

IdentityHashMap vs HashMap test - CPU usage

The post In Java What is a Difference Between IdentityHashMap and HashMap + Performance Comparison appeared first on Crunchify.

Enregistrer un commentaire

0 Commentaires