HashMap如何在Java中工作?
通过优锐课学习笔记分享,我们可以看到HashMap问题在工作面试中很常见。 这也是HashMaps在Java内部如何工作的一些深入说明,分享给大家参考学习。
HashMap在内部如何工作已成为几乎所有访谈中的一个普遍问题。 几乎每个人都知道如何使用HashMap或HashMap与Hashtable之间的区别。 但是,当问题为“ HashMap如何在内部工作?”时,许多人会失败。
这个问题的答案是,它基于哈希原理工作,但听起来并不那么简单。 哈希是一种使用算法将唯一代码分配给变量或属性的机制,从而可以轻松进行检索。 真正的哈希机制在应用于同一对象时应始终返回相同的hashCode()。
然后是一个问题:“哈希如何帮助存储和检索HashMap中的值?” 许多人会说该值将存储在存储桶中,并使用键进行检索。 如果你认为这是有效的,那么你绝对是错误的。 为了证明这一点,让我们看一下HashMap类:
/** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table;
那么HashMap中Entry []的用途是什么? HashMap将对象存储为Entry实例,而不是键和值。
什么是入门班?
HashMap有一个称为Entry Class的内部类,其中包含键和值。 还有一个叫做next的东西,稍后您将了解。
static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; ........ }
你知道HashMap将Entry实例存储在数组中,而不是作为键值对存储。 为了存储值,你将使用HashMap的put()方法。 让我们深入研究一下,看看它是如何工作的。
Put()方法如何在内部工作?
该代码将如下所示:
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; }
首先,它检查给定的密钥是否为null。如果给定键为null,则它将存储在零位置,因为null的哈希码将为零。
然后通过调用hashcode方法将哈希码应用于键.hashCode()。为了在数组范围内获得值,调用了hash(key.hashCode()),它对哈希码执行一些移位操作。
indexFor()方法用于获取存储Entry对象的确切位置。
接下来是最重要的部分-如果两个不同的对象具有相同的哈希码(例如Aa和BB将具有相同的哈希码),它将存储在同一存储桶中吗?为了解决这个问题,让我们考虑一下数据结构中的LinkedList。它将具有“下一个”属性,该属性将始终指向下一个对象,与Entry类中的下一个属性指向下一个对象的方式相同。使用这种方法,具有相同哈希码的不同对象将彼此相邻放置。
对于Collision,HashMap检查下一个属性的值。如果为null,则将Entry对象插入该位置。如果下一个属性不为null,则它将保持循环运行,直到下一个属性为null,然后将Entry对象存储在那里。
如何在HashMap中防止重复密钥?
众所周知,HashMap不允许重复键,即使当我们插入具有不同值的相同键时,也仅返回最新值。
import java.util.HashMap; import java.util.Map; public class HashMapEg { public static void main(String[] args) { Map map = new HashMap(); map.put(1, "sam"); map.put(1, "Ian"); map.put(1, "Scott"); map.put(null, "asdf"); System.out.println(map); } }
对于上面的代码,您将获得输出{null = asdf,1 = Scott},因为值sam和Ian将被替换为Scott。 那么,这是怎么发生的呢?
LinkedList中的所有Entry对象将具有相同的哈希码,但是HashMap使用equals()。 此方法检查相等性,因此如果key.equals(k)为true,它将替换Entry类中的值对象而不是键。 这样,可以防止插入重复密钥。
Get()方法如何在内部工作?
将使用put()方法中几乎相同的逻辑来检索值。
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; } 1,First, it gets the hash code of the key object, which is passed, and finds the bucket location. 2,If the correct bucket is found, it returns the value. 3,If no match is found, it returns null.
如果两个键具有相同的Hashcode会发生什么?
此处将使用相同的冲突解决机制。 key.equals(k)将一直检查到它为true,如果为true,则返回它的值。
我希望本文能阐明麻烦的HashMap内部机制。 祝大家学习愉快!如有不足之处,欢迎补充评论。
抽丝剥茧,细说架构那些事--优锐课
HashMap如何在Java中工作?的更多相关文章
- 如何在JAVA中实现一个固定最大size的hashMap
如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...
- 如何在java中使用sikuli进行自动化测试
很早之前写过一篇介绍sikuli的文章.本文简单介绍如何在java中使用sikuli进自动化测试. 图形脚本语言sikuli sikuli IDE可以完成常见的单击.右击.移动到.拖动等鼠标操作,ja ...
- 如何在Java中调用Python代码
有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...
- 如何在java中跳出当前多重嵌套循环?有几种方法?
如何在java中跳出当前多重嵌套循环?有几种方法? - 两种方法 - 1.在外层循环定义标记 ok: for(int i=0;i<100;i++){ ...
- 用代码说话:如何在Java中实现线程
并发编程是Java语言的重要特性之一,"如何在Java中实现线程"是学习并发编程的入门知识,也是Java工程师面试必备的基础知识.本文从线程说起,然后用代码说明如何在Java中实现 ...
- 如何在Java中测试类是否是线程安全的
通过优锐课的java核心笔记中,我们可以看到关于如何在java中测试类是否线程安全的一些知识点汇总,分享给大家学习参考. 线程安全性测试与典型的单线程测试不同.为了测试一个方法是否是线程安全的,我们需 ...
- 如何在 Java 中实现无向环和有向环的检测
无向环 一个含有环的无向图如下所示,其中有两个环,分别是 0-2-1-0 和 2-3-4-2: 要检测无向图中的环,可以使用深度优先搜索.假设从顶点 0 出发,再走到相邻的顶点 2,接着走到顶点 2 ...
- 如何在 Java 中实现最小生成树算法
定义 在一幅无向图 \(G=(V,E)\) 中,\((u, v)\) 为连接顶点 \(u\) 和顶点 \(v\) 的边,\(w(u,v)\) 为边的权重,若存在边的子集 \(T\subseteq E\ ...
- 如何在 Java 中实现 Dijkstra 最短路算法
定义 最短路问题的定义为:设 \(G=(V,E)\) 为连通图,图中各边 \((v_i,v_j)\) 有权 \(l_{ij}\) (\(l_{ij}=\infty\) 表示 \(v_i,v_j\) 间 ...
随机推荐
- java_计算个人所得税
// import java.util.Scanner;public class Test10{ public static void main(String[] args){ // 创建Scanne ...
- 001_Java概述与环境搭建
Java由来: SUN公司开发,95年推出,96年推出JDK1.0版本 09年被Oracle(甲骨文)收购 詹姆斯·高斯林被称作“Java之父” JavaSE:Java Standard Editoi ...
- 【Eclipse】Spring Tool Suite插件
Spring Tool Suite插件 最新下载地址:https://spring.io/tools3/sts/all 以前下载地址:https://spring.io/tools3/sts/lega ...
- Spring Cloud第十篇 | 分布式配置中心Config
本文是Spring Cloud专栏的第十篇文章,了解前九篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Clo ...
- Nginx优化之一
一.Nginx安全优化 1.1:隐藏nginx版本信息 官方配置参数说明:http://nginx.org/en/docs/http/ngx_http_core_module.html#server_ ...
- C# 模拟浏览器并自动操作
本文主要讲解通过WebBrowser控件打开浏览页面,并操作页面元素实现自动搜索功能,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点 WebBrowser:用于在WinForm窗体中,模拟浏览 ...
- 实验:使用GDB查看结构体在内存中的存储方式
结构体在内存中的表示形式是怎么样的? 结构体在内存中和普通变量存储没有太大的区别. 首先我们看看,计算机如何读取普通变量: 普通变量例如int是占据4个字节,计算机读内存的时候会从起始地址开始读, ...
- C语言笔记 07_枚举&指针
emum(枚举) 枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读. 枚举语法定义格式为: enum 枚举名 {枚举元素1,枚举元素2,--}; 举个例子,比如:一星期有 7 天,如果 ...
- cesium计算当前地图范围extent以及近似当前层级zoom
前言 cesium 官网的api文档介绍地址cesium官网api,里面详细的介绍 cesium 各个类的介绍,还有就是在线例子:cesium 官网在线例子,这个也是学习 cesium 的好素材. 内 ...
- num2str(A, format)
str = num2str(A, format)A: 数值类型的数组或者是单个的数值format:指定数字转换为字符串的格式,通常’%11.4g’是默认的.也可以指定转换为几位的字符串,不足用0填充, ...