HashMap如何在Java中工作

面试中最常见的问题是“ 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。您将看到如下结构。
HashMapStructure1 现在,从上图可以观察到以下几点

  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概念。
HashMapStructure2 因此,现在,如果您对哈希图的结构有了很好的了解,那么让我们通过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设计师已经把另一个函数调用的散列(),接受作为argument.If您想了解更多关于散列()函数上面计算哈希值,你可以参考散列和indexFor hashmap中的方法 。
  3. indexFor(hash,table.length)用于计算表数组中的确切索引,以存储Entry对象。
  4. 正如我们在示例中看到的那样,如果两个关键对象具有相同的哈希码(称为冲突 ),则它将以链表的形式存储。因此在这里,我们将遍历链表。
  • 如果我们刚刚计算出的那个索引上没有元素,那么它将直接把Entry对象放在那个索引上。
  • 如果该索引处存在元素,则它将迭代直到获得Entry-> next作为null。然后当前的Entry对象成为该链表中的下一个节点
  • 如果我们再次放置相同的键,从逻辑上讲应该替换旧值该怎么办。 是的,它会这样做。在迭代时,将通过调用equals()方法( key.equals(k) )检查键是否相等,如果此方法返回true,则它将值对象替换为当前Entry的值对象。

得到:

让我们看一下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()方法

参考:来自JCG合作伙伴 Arpit Mandliya的HashMap如何在Java中工作 ,有关Java框架和初学者博客的设计模式 。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

input上传文件个数控制

HTML: 1 <h3>请上传[2,5]个文件</h3>2 <form action"" enctype"multipart/form-data">3 <input type"file" name"file" multiple"multiple" id"file" onchange"fileCo…

东北农业大计算机排名,黑龙江高校排名更新,东北林大排名第3,东油排名第8...

东北地区的经济发展起步比较早&#xff0c;属于我国的老牌重工业基地&#xff0c;被称为“新中国工业的摇篮”&#xff0c;是我国最重要的经济支柱。这里的高校也因此而受到重视&#xff0c;为日后的发展奠定了扎实的基础&#xff1b;随着国家经济重心的转移&#xff0c;因为地…

150个Java面试问答-最终清单(PDF下载)

我们的Java面试问题和答案集合全都涉及可以在Java面试中使用的不同类型的问题&#xff0c;以使雇主可以测试您在Java和面向对象编程方面的技能。 在以下各节中&#xff0c;我们将讨论有关面向对象编程及其特性的Java面试问题&#xff0c;有关Java及其功能的一般问题&#xff0…

计算机电子电路原理图,简单电路图入门-电路原理图入门知识图解

简单电路图入门-电路原理图入门知识图解电路图的分类简单电路图入门&#xff0c;常遇到的电子电路图有原理图、方框图、装配图和印版图等。1、原理图原理图就是用来体现电子电路的工作原理的一种电路图&#xff0c;又被叫做“电原理图”。这种图由于它直接体现了电子电路的结构…

老是不中,算了算“双色球”和“3D”,全买到底要多少¥¥。。(C 代码)

最近也做发财梦&#xff0c;买了段时间得彩票&#xff0c;不得要领&#xff0c;今天写了两个小程序&#xff0c;算算把所有号码组合都买下到底要多少&#xffe5;&#xffe5;。。还是先贴个规则吧&#xff1b;双色球&#xff1a;从 1~33 中选6个不重复得数值&#xff08;红球&…

pycharm 中 import requests 报错

一 , 使用Pycharm来抓取网页的时候&#xff0c;要导入requests模块&#xff0c;但是在pycharm中 import requests 报错。 原因&#xff1a; python中还没有安装requests库 解决办法&#xff1a; 1.先找到自己python安装目录下的pip 2.在自己的电脑里打开cmd窗口。先点击开始栏&…

dell 计算机硬盘保护,dell台式机硬盘保护 怎样取消

工具/原料十字型螺丝刀一把新台式机硬盘一块方法/步骤1.把新购置的硬盘拆开&#xff0c;以备后面使用&#xff1a;2.拆下机箱的侧面板&#xff0c;注意&#xff0c;侧面板有两颗螺丝固定&#xff0c;需要先卸下&#xff0c;之后向一侧方向拉出侧面板就可以了&#xff0c;拆下侧…

安全建设之平台搭建

一、信息搜集类 基础信息 基础信息搜集包括ip&#xff0c;域名&#xff0c;端口&#xff0c;框架&#xff0c;组件信息。Ip、域名甲方可通过运维同事获取&#xff0c;其他获取方式仁者见仁智者见智。端口&#xff0c;需要我们根据获取的域名、ip进行端口扫描&#xff0c;这里推…

第四章 生命周期函数--35 vue-resource发起get、post、jsonp请求

vue-resource 官网 https://github.com/pagekit/vue-resource 1 <!DOCTYPE html>2 <html lang"en">3 4 <head>5 <meta charset"utf-8">6 <meta name"viewport" content"widthdevice-width,initial-sc…

Enterprise Library Step By Step系列(十一):异常处理应用程序块——入门篇

Enterprise Library Step By Step系列&#xff08;十一&#xff09;&#xff1a;异常处理应用程序块——入门篇 作者&#xff1a;Terrylee 一&#xff0e;概述 使开发人员和决策人员能够针对发生在企业应用程序体系结构层的异常处理创建一致的策略。它的实现方法如下&#xff1…

qt商业版和开源版的区别_微擎商业版系统V2.0.9全开源版纯净框架

微擎商业版系统V2.0.9全开源版纯净框架_全新界面无后门无任何限制。该源码不含任何安装模块&#xff0c;最重要的是该版本是一键安装版&#xff0c;主要你上传到服务器上&#xff0c;然后直接运行域名就会直接进入安装环境&#xff0c;不会像网络上的其他版本&#xff0c;还需要…

js 的起源故事

"1994年&#xff0c;网景公司&#xff08;Netscape&#xff09;发布了Navigator浏览器0.9版。这是历史上第一个比较成熟的网络浏览器&#xff0c;轰动一时。但是&#xff0c;这个版本的浏览器只能用来浏览&#xff0c;不具备与访问者互动的能力。......网景公司急需一种网…

CMD命令也要用好

以前一些程序需要执行一些Dos命令&#xff0c;一般都是写成一个Bat文件&#xff0c;然后通过Shel来调用&#xff0c;实际上一些简单得用法完全可以这样用&#xff1a;VBA.Shell "cmd /c cmd /? > c:\cmdhelp.txt"VBA.Shell "cmd /c Type c:\cmdhelp.txt >…

广元南山隧道南河互通立交图_广元城区一隧道工程竣工时间已定,今后出行更加方便了!...

4月15日&#xff0c;伴着轰隆的机械声&#xff0c;记者踏入国道212线南山隧道工程项目建设现场&#xff0c;突然眼前飘来一阵细密小雨&#xff0c;抬头望去&#xff0c;原来是建设边坡上一排白色雾炮机正在进行降尘作业。记者看到&#xff0c;数控钢筋加工厂内工人们正抓紧预制…

Java EE 7:新增功能???

我有点“晚点”&#xff0c;可以这么说……就Java EE 7的 “博客”而言。 自2013年6月发布以来&#xff0c;已经差不多10个月了 &#xff0c;但是它仍然相对较新。 就我个人而言&#xff0c;仅仅是因为它的易用性和所购买的功能范围之广&#xff0c;我对此感到很兴奋。但是&…

浏览器的同源策略及跨域解决方案

同源策略 一个源的定义 如果两个页面的协议&#xff0c;端口&#xff08;如果有指定&#xff09;和域名都相同&#xff0c;则两个页面具有相同的源。 举个例子&#xff1a; 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示例: URL结果原因http://a.xyz.com/dir2/ot…

计算机病毒及其防治评课,区初中信息技术教研活动公开课评课感想

今天上午&#xff0c;在我校成功举行了区初中信息技术教研活动&#xff0c;总共开设了三节课&#xff0c;都是由我校老师执教的。听后受益匪浅&#xff0c;感受颇深&#xff0c;以下是本人的评课感想。一、首先说一下三位老师的共同点&#xff1a;1、三位老师都用了导学案&…

Django—路由层,视图层

路由层urls 浏览器会自动给url后加一个“/” django会自动给路由的正则表达式前面加一个“/” django会给任何不带“/”结尾的url语句添加“/”&#xff08;可设置&#xff09; 短路路由规则&#xff1a;匹配到第一条就忽略后面所有&#xff01; 所以路由顺序很重要&#xff01…

分数怎么化成带分数_人教版五年级下册第4单元带分数及把假分数化成整数或带分数教学视频+知识点...

|点击题目下方蓝字一键关注 小学生知识库|【教学视频】分数的分类与互化【知识点】带分数的意义和特征&#xff1a;像…这样由整数和真分数合成的数叫做带分数。假分数化成整数或带分数的方法是什么&#xff1f;①当假分数的分子是分母的倍数时&#xff0c;这个假分数可以化成整…

Java 8功能教程– ULTIMATE指南(PDF下载)

编者注&#xff1a;在本文中&#xff0c;我们提供了全面的Java 8功能教程。 自Java 8公开发布以来已经有一段时间了&#xff0c;所有迹象都表明这是一个非常重要的版本。 我们在Java Code Geeks处提供了大量教程&#xff0c;例如“ 玩Java 8 – Lambda和并发” &#xff0c;“…