java中hashmap

面试中最常见的问题是“ HashMap如何在Java中工作”,“ HashMap的获取和放置方法如何在内部工作”。 在这里,我试图通过一个简单的示例来解释内部功能。 而不是通过理论,我们将首先从示例开始,以便您可以更好地理解,然后我们将了解get和put函数如何在Java中工作。
让我们举一个非常简单的例子。 我有一个Country类,我们将使用Country类对象作为键,并使用其大写名称(字符串)作为值。 下面的示例将帮助您了解如何将这些键值对存储在哈希图中。

1. Country.java

package org.arpit.javapostsforlearning;
public class Country {String name;long population;public Country(String name, long population) {super();this.name = name;this.population = population;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getPopulation() {return population;}public void setPopulation(long population) {this.population = population;}// If length of name in country object is even then return 31(any random number) and if odd then return 95(any random number).// 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.@Overridepublic int hashCode() {if(this.name.length()%2==0)return 31;else return 95;}@Overridepublic boolean equals(Object obj) {Country other = (Country) obj;if (name.equalsIgnoreCase((other.name)))return true;return false;}}

如果您想了解有关对象的哈希码和equals方法的更多信息,可以在Java中引用hashcode()和equals()方法。

2. HashMapStructure.java(主类)

import java.util.HashMap;
import java.util.Iterator;public class HashMapStructure {/*** @author Arpit Mandliya*/public static void main(String[] args) {Country india=new Country("India",1000);Country japan=new Country("Japan",10000);Country france=new Country("France",2000);Country russia=new Country("Russia",20000);HashMap<country,string> countryCapitalMap=new HashMap<country,string>();countryCapitalMap.put(india,"Delhi");countryCapitalMap.put(japan,"Tokyo");countryCapitalMap.put(france,"Paris");countryCapitalMap.put(russia,"Moscow");Iterator<country> countryCapitalIter=countryCapitalMap.keySet().iterator();//put debug point at this linewhile(countryCapitalIter.hasNext()){Country countryObj=countryCapitalIter.next();String capital=countryCapitalMap.get(countryObj);System.out.println(countryObj.getName()+"----"+capital);}}}
</country></country,string></country,string>

现在,在第23行放置调试点,然后右键单击project-> debug as-> java应用程序。 程序将在第23行停止执行,然后右键单击countryCapitalMap,然后选择watch。您将看到以下结构。

现在,从上图可以观察到以下几点

  1. 有一个称为table的Entry []数组,其大小为16。
  2. 该表存储Entry类的对象。 HashMap类具有一个称为Entry的内部类。此Entry具有键值作为实例变量。 让我们看一下入口类的结构Entry Structure。
  3. static class Entry implements Map.Entry
    {final K key;V value;Entry next;final int hash;...//More code goes here
    }
  4. 每当我们尝试将任何键值对放入哈希图中时,都会为键值实例化Entry类对象,并且该对象将存储在上述Entry [](表)中。 现在您一定想知道,上面创建的Enrty对象将存储在哪里(表中的确切位置)。 答案是,通过调用Hascode()方法为密钥计算哈希码。 该哈希码用于计算上述Entry []表的索引。
  5. 现在,如果您在上图中的数组索引10处看到,它具有一个名为HashMap $ Entry的Entry对象。
  6. 我们在hashmap中放置了4个键值,但似乎只有2个!!!因为这是因为如果两个对象具有相同的哈希码,则它们将存储在相同的索引处。 现在问题出现了如何? 它以LinkedList的形式存储对象(逻辑上)。

那么如何计算上述国家/地区键值对的哈希码。

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

下图将清楚地说明LinkedList概念。

因此,现在,如果您对哈希图结构有很好的了解,那么让我们通过put和get方法。

放置:

让我们看一下put方法的实现:

/*** Associates the specified value with the specified key in this map. If the* map previously contained a mapping for the key, the old value is* replaced.** @param key*            key with which the specified value is to be associated* @param value*            value to be associated with the specified key* @return the previous value associated with <tt>key</tt>, or <tt>null</tt>*         if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return*         can also indicate that the map previously associated*         <tt>null</tt> with <tt>key</tt>.)*/public V put(K key, V value) {if (key == null)return putForNullKey(value);int hash = hash(key.hashCode());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;}

现在让我们逐步了解上面的代码

  1. 检查键对象是否为空。 如果key为null,则它将存储在table [0]中,因为null的哈希码始终为0。
  2. 调用关键对象的hashcode()方法并计算哈希码。 该哈希码用于查找用于存储Entry对象的数组的索引。 有时可能会发生这种哈希代码函数编写不佳的情况,因此JDK设计人员放置了另一个名为hash()的函数,该函数将以上计算的哈希值作为参数。如果您想了解更多有关hash()函数的信息,可以引用hash和indexFor hashmap中的方法 。
  3. indexFor(hash,table.length)用于计算表数组中的确切索引,以存储Entry对象。
  4. 正如我们在示例中看到的那样,如果两个关键对象具有相同的哈希码(称为冲突 ),则它将以链表的形式存储。因此在这里,我们将遍历链表。
  • 如果我们刚刚计算出的那个索引上没有元素,那么它将直接将Entry对象放在那个索引上。
  • 如果该索引处存在元素,则它将迭代直到获得Entry-> next为null。然后当前的Entry对象成为该链表中的下一个节点
  • 如果我们再次放置相同的密钥,从逻辑上讲应该替换旧值该怎么办。 是的,它将这样做。在迭代时将通过调用equals()方法( key.equals(k) )检查键是否相等,如果此方法返回true,则它将值对象替换为当前Entry的值对象。

得到:

让我们看一下get get的实现:

/*** Returns the value to which the specified key is mapped, or {@code null}* if this map contains no mapping for the key.** <p>* More formally, if this map contains a mapping from a key {@code k} to a* value {@code v} such that {@code (key==null ? k==null :* key.equals(k))}, then this method returns {@code v}; otherwise it returns* {@code null}. (There can be at most one such mapping.)** </p><p>* A return value of {@code null} does not <i>necessarily</i> indicate that* the map contains no mapping for the key; it's also possible that the map* explicitly maps the key to {@code null}. The {@link #containsKey* containsKey} operation may be used to distinguish these two cases.** @see #put(Object, Object)*/public V get(Object key) {if (key == null)return getForNullKey();int hash = hash(key.hashCode());for (Entry<k , V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {Object k;if (e.hash == hash && ((k = e.key) == key || key.equals(k)))return e.value;}return null;}

当您了解了hashmap的put功能时。 因此,了解获取功能非常简单。 如果传递任何键以从哈希图获取值对象。

  1. 检查键对象是否为空。 如果key为null,则将返回Object的值位于table [0]。
  2. 调用关键对象的hashcode()方法并计算哈希码。
  3. indexFor(hash,table.length)用于使用生成的哈希码来获取Entry对象来计算表数组中的精确索引。
  4. 在表数组中获取索引后,它将遍历链表并通过调用equals()方法检查键是否相等,如果返回true,则返回Entry对象的值,否则返回null。

记住要点:

  • HashMap有一个称为Entry的内部类,用于存储键值对。
  • 上面的Entry对象存储在称为table的Entry [](Array)中
  • 表的索引在逻辑上称为存储桶,它存储链表的第一个元素
  • 关键对象的hashcode()用于查找该Entry对象的存储桶。
  • 如果两个键对象具有相同的哈希码,则它们将进入表数组的同一存储桶中。
  • 关键对象的equals()方法用于确保关键对象的唯一性。
  • 完全不使用值对象的equals()和hashcode()方法
参考: HashMap如何在我们的JCG合作伙伴 Arpit Mandliya在Java框架和面向初学者博客的设计模式下在Java中工作 。

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

java中hashmap

java中hashmap_HashMap如何在Java中工作相关推荐

  1. cmd中加载java源文件_如何在cmd中编译和运行java源文件

    如何在cmd中编译和运行java源文件 首先写一个名为HelloWorld.java的java源文件,存储在如C:/java/src的地址,我们再假设待会要存储的位置是C:/java/bin,则我们做 ...

  2. java 合并pdf,如何在Java中合并PDF

    如何在Java中合并PDF 为小型企业和大型企业,保持 您的 重要 文件, 组织将提高您的工作流程,并成倍增长你的组织的工作效率. PDF文档由于其接受的输入格式的类型的安全性和灵活性,通常是共享大量 ...

  3. java发送gmail_如何在Gmail中轻松通过电子邮件发送人群

    java发送gmail Mailing lists are an old tool in the email arsenal, but their implementation in Gmail is ...

  4. java 联合_如何在java中进行联合,相交,区分和反向数据

    我想在Java中有联合,相交,差异和反向操作. 首先我有2个ArrayList< Integer> a = [0,2,4,5,6,8,10] b = [5,6,7,8,9,10] 一个工会 ...

  5. java 运费_如何在Java中创建运费成本计算器

    我正在创建计算器来计算运费.代码是这样的:如何在Java中创建运费成本计算器 class ShippingCalc { public static void main(String[] args) { ...

  6. java 关闭jpanel_如何在Java中关闭Jpanel程序

    我正在制作一个Java游戏,我需要一些关于如何操作的建议.如何在Java中关闭Jpanel程序 目前我使用2个不同的.java文件来制作游戏.我有一个扩展JFrame的主程序,我调用扩展JPanel的 ...

  7. java 二叉查找树_如何在Java中实现二叉搜索树( binary search tree)?

    二叉搜索树或BST是一种流行的数据结构,用于保持元素的顺序.二叉搜索树是二叉树,其中左子节点的值小于或等于父节点,右子节点的值大于或等于父节点.由于它是二叉树,它只能有0,1或2个子节点.二叉搜索树之 ...

  8. java spring scope_如何在Spring中自定义scope的方法示例

    大家对于 Spring 的 scope 应该都不会默认.所谓 scope,字面理解就是"作用域"."范围",如果一个 bean 的 scope 配置为 sing ...

  9. amd cpu不能在cmd环境下运行java代码_如何在Windows10中配置java的JDK环境

    今天给大家分享一下如何配置java的JDK环境.操作步骤如下: 1.下载好 jdk 的安装文件,我下载的是 jdk-10.0.1_windows-x64_bin.exe 这个版本的安装文件: 2.使用 ...

最新文章

  1. 商用故事|泰华amp;华为手牵手,点亮城市照明
  2. python主要用途-python的主要用途是什么
  3. react-dnd 拖拽
  4. Android复习04(适配器 Get()请求 适配器 getView()方法 Post()请求 保存Cookie 流转字符串 从网上获取图片 重点考Json解析)
  5. python对象列表转换为字典_python – 将csv.DictReader对象转换为字典列表...
  6. python-词云wordcloud-0223
  7. 程序路漫漫兮,上下而求索
  8. 使用接口更改已装箱的值类型中的字段
  9. MailMail正式发布!注册码免费发放活动开启!(已结束~~不要再回复咧~)
  10. tableview分割线
  11. BZOJ2535: [Noi2010]Plane 航空管制2(拓扑排序 贪心)
  12. composer 下载包慢的解决方法
  13. 开课吧课堂:数据可视化的制作方法与准则有哪些?
  14. Unicode官网Code Charts下载。
  15. html5css3背景下雪,HTML5 CSS3下雪奥运五环背景动画特效
  16. 软件导出excel时提示没有注册类
  17. 企鹅杏仁集团完成2.5亿美元融资,投后估值超过10亿美元...
  18. node.js 安装步骤(超详细小白版) 和 node安装指定版本
  19. ERP系统模块完全解析──主生产计划MPS
  20. 美丽链——通过买套内衣读懂“区块链”?

热门文章

  1. The 2020 ICPC Asia Macau Regional Contest J. Jewel Grab(数颜色+链表)
  2. ARC107——D - Number of Multisets
  3. Oracle入门(一)之入门级知识详解
  4. JavaFX图表(四)之面积图
  5. art-template 入门(二)之安装
  6. java8 hash算法
  7. Spring AOP知识点简介
  8. mybatis简单案例源码详细【注释全面】——前期准备
  9. getOrDefault()和subList()
  10. JS中闭包的应用自定义JS模块2