https://www.javacodegeeks.com/2014/03/how-hashmap-works-in-java.html

 

Most common interview questions are “How HashMap works in java”, “How get and put method of HashMap work internally”. Here I am trying to explain internal functionality with an easy example. Rather than going through theory, we will start with example first, so that you will get better understanding and then we will see how get and put function work in java.
Lets take a very simple example. I have a Country class, we are going to use Country class object as key and its capital name(string) as value. Below example will help you to understand, how these key value pair will be stored in hashmap.

1. Country.java

01 package org.arpit.javapostsforlearning;
02 public class Country {
03  
04  String name;
05  long population;
06  
07  public Country(String name, long population) {
08   super();
09   this.name = name;
10   this.population = population;
11  }
12  public String getName() {
13   return name;
14  }
15  public void setName(String name) {
16   this.name = name;
17  }
18  public long getPopulation() {
19   return population;
20  }
21  public void setPopulation(long population) {
22   this.population = population;
23  }
24  
25  // If length of name in country object is even then return 31(any random number) and if odd then return 95(any random number).
26  // This is not a good practice to generate hashcode as below method but I am doing so to give better and easy understanding of hashmap.
27  @Override
28  public int hashCode() {
29   if(this.name.length()%2==0)
30    return 31;
31   else
32    return 95;
33  }
34  @Override
35  public boolean equals(Object obj) {
36  
37   Country other = (Country) obj;
38    if (name.equalsIgnoreCase((other.name)))
39    return true;
40   return false;
41  }
42  
43 }

If you want to understand more about hashcode and equals method of object, you may refer hashcode() and equals() method in java

2. HashMapStructure.java(main class)

01 import java.util.HashMap;
02 import java.util.Iterator;
03    
04 public class HashMapStructure {
05    
06     /**
07      * @author Arpit Mandliya
08      */
09     public static void main(String[] args) {
10            
11         Country india=new Country("India",1000);
12         Country japan=new Country("Japan",10000);
13            
14         Country france=new Country("France",2000);
15         Country russia=new Country("Russia",20000);
16            
17         HashMap<country,string> countryCapitalMap=new HashMap<country,string>();
18         countryCapitalMap.put(india,"Delhi");
19         countryCapitalMap.put(japan,"Tokyo");
20         countryCapitalMap.put(france,"Paris");
21         countryCapitalMap.put(russia,"Moscow");
22            
23         Iterator<country> countryCapitalIter=countryCapitalMap.keySet().iterator();//put debug point at this line
24         while(countryCapitalIter.hasNext())
25         {
26             Country countryObj=countryCapitalIter.next();
27             String capital=countryCapitalMap.get(countryObj);
28             System.out.println(countryObj.getName()+"----"+capital);
29             }
30         }
31    
32    
33 }
34 </country></country,string></country,string>

Now put debug point at line 23 and right click on project->debug as-> java application. Program will stop execution at line 23 then right click on countryCapitalMap then select watch.You will be able to see structure as below.
 

Now From above diagram, you can observe following points

    1. There is an Entry[] array called table which has size 16.
    2. This table stores Entry class’s object. HashMap class has a inner class called Entry.This Entry have key value as instance variable. Lets see structure of entry class Entry Structure.
1 static class Entry implements Map.Entry
2 {
3         final K key;
4         V value;
5         Entry next;
6         final int hash;
7         ...//More code goes here
8 }
  1. Whenever we try to put any key value pair in hashmap, Entry class object is instantiated for key value and that object will be stored in above mentioned Entry[](table). Now you must be wondering, where will above created Enrty object get stored(exact position in table). The answer  is, hash code is calculated for a key by calling Hascode() method. This hashcode is used to calculate index for above Entry[] table.
  2. Now, If you see at array index 10 in above diagram, It has an Entry object named HashMap$Entry.
  3. We have put 4 key-values in hashmap but it seems to have only 2!!!!This is because if two objects have same hashcode, they will be stored at same index. Now question arises how? It stores objects in a form of LinkedList(logically).

So how hashcode of above country key-value pairs are calculated.

1 Hashcode for Japan = 95 as its length is odd.
2 Hashcode for India =95 as its length is odd
3 HashCode for Russia=31 as its length is even.
4 HashCode for France=31 as its length is even.

Below diagram will explain LinkedList concept clearly.
 

So now if you have good understanding of hashmap structure,Lets go through put and get method.

Put :

Lets see implementation of put method:

01 /**
02   * Associates the specified value with the specified key in this map. If the
03   * map previously contained a mapping for the key, the old value is
04   * replaced.
05   *
06   * @param key
07   *            key with which the specified value is to be associated
08   * @param value
09   *            value to be associated with the specified key
10   * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
11   *         if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
12   *         can also indicate that the map previously associated
13   *         <tt>null</tt> with <tt>key</tt>.)
14   */
15  public V put(K key, V value) {
16   if (key == null)
17    return putForNullKey(value);
18   int hash = hash(key.hashCode());
19   int i = indexFor(hash, table.length);
20   for (Entry<k , V> e = table[i]; e != null; e = e.next) {
21    Object k;
22    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
23     V oldValue = e.value;
24     e.value = value;
25     e.recordAccess(this);
26     return oldValue;
27    }
28   }
29  
30   modCount++;
31   addEntry(hash, key, value, i);
32   return null;
33  }

now lets understand above code step by step

  1. Key object is checked for null. If key is null then it will be stored at table[0] because hashcode for null is always 0.
  2. Key object’s hashcode() method is called and hash code is calculated. This hashcode is used to find index of array for storing Entry object. It may happen sometimes that, this hashcode function is poorly written so JDK designer has put another function called hash() which takes above calculated hash value as argument.If you want to learn more about hash() function, you can refer hash and indexFor method in hashmap.
  3. indexFor(hash,table.length)  is used to calculate exact index in table array for storing the Entry object.
  4. As we have seen in our example, if two key objects have same hashcode(which is known as collision) then it will be stored in form of linkedlist.So here, we will iterate through our linkedlist.
  • If there is no element present at that index which we have just calculated then it will directly put our Entry object at that index.
  • If There is element present at that index then it will iterate until it gets Entry->next as null.Then current Entry object become next node in that linkedlist
  • What if we are putting same key again, logically it should replace old value. Yes,it will do that.While iterating it will check key equality by calling equals() method(key.equals(k)), if this method returns true then it replaces value object with current Entry’s value object.

Get:

Lets see implementation of get now:

01 /**
02   * Returns the value to which the specified key is mapped, or {@code null}
03   * if this map contains no mapping for the key.
04   *
05   * <p>
06   * More formally, if this map contains a mapping from a key {@code k} to a
07   * value {@code v} such that {@code (key==null ? k==null :
08   * key.equals(k))}, then this method returns {@code v}; otherwise it returns
09   * {@code null}. (There can be at most one such mapping.)
10   *
11   * </p><p>
12   * A return value of {@code null} does not <i>necessarily</i> indicate that
13   * the map contains no mapping for the key; it's also possible that the map
14   * explicitly maps the key to {@code null}. The {@link #containsKey
15   * containsKey} operation may be used to distinguish these two cases.
16   *
17   * @see #put(Object, Object)
18   */
19  public V get(Object key) {
20   if (key == null)
21    return getForNullKey();
22   int hash = hash(key.hashCode());
23   for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
24    Object k;
25    if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
26     return e.value;
27   }
28   return null;
29  }

As you got the understanding on put functionality of hashmap. So to understand get functionality is quite simple. If you pass any key to get value object from hashmap.

  1. Key object is checked for null. If key is null then value of Object resides at table[0] will be returned.
  2. Key object’s hashcode() method is called and hash code is calculated.
  3. indexFor(hash,table.length)  is used to calculate exact index in table array using generated hashcode for getting the Entry object.
  4. After getting index in table array, it will iterate through linkedlist and check for key equality by calling equals() method and if it returns true then it returns the value of Entry object else returns null.

Key points to Remeber:

  • HashMap has a inner class called Entry which stores key-value pairs.
  • Above Entry object is stored in Entry[ ](Array) called table
  • An index of table is logically known as bucket and it stores first element of linkedlist
  • Key object’s hashcode() is used to find bucket of that Entry object.
  • If two key object ‘s have same hashcode , they will go in same bucket of table array.
  • Key object ‘s equals() method is used to ensure uniqueness of key object.
  • Value object  ‘s equals() and hashcode() method is not used at all

How HashMap works in java 2的更多相关文章

  1. How HashMap works in Java

    https://www.javainterviewpoint.com/hashmap-works-internally-java/ How a HashMap Works internally has ...

  2. HashMap如何工作 - Java

    大多数人应该会同意HashMap是现在面试最喜欢问的主题之一.我和同事常常进行讨论,并很有帮助.现在,我继续和大家讨论. 我假设你对HashMap的内部工作原理感兴趣,并且你已经知道了基本的HashM ...

  3. SpringMvc中Hashmap操作遇到 java.util.ConcurrentModificationException: null

    代码按照网上修改为类似,还不能解决问题 for (Iterator<String> it = target.keySet().iterator(); it.hasNext(); ) { i ...

  4. HashTable HashMap HashSet区别(java)

    Hashtable: 1. key和value都不许有null值 2. 使用enumeration遍历 3. 同步的,每次只有一个线程能够访问 4. 在java中Hashtable是H大写,t小写,而 ...

  5. HashMap如何在Java中工作?

    通过优锐课学习笔记分享,我们可以看到HashMap问题在工作面试中很常见. 这也是HashMaps在Java内部如何工作的一些深入说明,分享给大家参考学习. HashMap在内部如何工作已成为几乎所有 ...

  6. JSONObject JSONArray json字符串 HashMap ArryList 在java开发中用到的数据结构

    1.JSONObject  长成这样的:   { "key1":value1, "key2":value2, "key3":value3} ...

  7. Understanding How Graal Works - a Java JIT Compiler Written in Java

    https://chrisseaton.com/truffleruby/jokerconf17/ https://chrisseaton.com/truffleruby/tenthings/ http ...

  8. LRU hashMap(拉链) + 双向链表 java实现

    //基于 hash (拉链法) + 双向链表,LRUcache //若改为开放寻址,线性探测法能更好使用cpuCache public class LRU { private class Node { ...

  9. Java集合框架(Collection Framework)学习之 HashMap

    从API文档可以得到HashMap的以下几个特点: 基于哈希表(hash table)实现,并且是链式哈希表 允许空值和空键(null=null 键值对) HashMap与Hashtable基本相同, ...

随机推荐

  1. 我的MQ笔记

    1.安装IBM MQ 1.1.安装先决条件: (1)WebSphere  Eclipse  Platform  V3.01 (2)为Windows域用户配置WebSphere MQ用户 1.2.安装程 ...

  2. ASP.NET开发,从二层至三层,至面向对象 (2)

    继续上一篇<ASP.NET开发,从二层至三层,至面向对象>http://www.cnblogs.com/insus/p/3822624.html .我们了解到怎样把自己的程序由二层变为三层 ...

  3. 呼叫WCF Service的方法出现Method not allowed异常

    asp.net mvc练习程序,经常性在家里电脑,笔记本或是公司的电脑之间拷贝与粘贴,如果忘记携带最新的练习程序,一些小功能只能重新写了.如前一篇<ASP.NET MVC呼叫WCF Servic ...

  4. maven根据不同的运行环境,打包不同的配置文件

    使用maven管理项目中的依赖,非常的方便.同时利用maven内置的各种插件,在命令行模式下完成打包.部署等操作,可方便后期的持续集成使用. 但是每一个maven工程(比如web项目),开发人员在开发 ...

  5. JS 随机排序算法

    https://www.cnblogs.com/getdaydayup/p/6592154.html 使用JS编写一个方法 让数组中的元素每次刷新随机排列 法一: var arr =[1,2,3,4] ...

  6. C# 最大二叉堆算法

    C#练习二叉堆算法. namespace 算法 { /// <summary> /// 最大堆 /// </summary> /// <typeparam name=&q ...

  7. [日常] Go语言圣经-指针对象的方法-bit数组习题2

    练习 6.3: (*IntSet).UnionWith会用|操作符计算两个集合的交集,我们再为IntSet实现另外的几个函数IntersectWith(交集:元素在A集合B集合均出现),Differe ...

  8. Spring Boot使用layui的字体图标时无法正常显示 解决办法

    在html文件使用字体图标并且预览时正常,但是启动工程后显示不正常,浏览器调试界面显示字体文件无法decode: Failed to decode downloaded font: xxxxx 如图所 ...

  9. HDFS 命令大全

    目录 概要 用户命令 dfs 命令 追加文件内容 查看文件内容 得到文件的校验信息 修改用户组 修改文件权限 修改文件所属用户 本地拷贝到 hdfs hdfs 拷贝到本地 获取目录,文件数量及大小 h ...

  10. Median(vector+二分)

    Median Time Limit: 5 Seconds Memory Limit: 65536 KB The median of m numbers is after sorting them in ...