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\) 间 ...
随机推荐
- 大数据学习笔记——Hbase高可用+完全分布式完整部署教程
Hbase高可用+完全分布式完整部署教程 本篇博客承接上一篇sqoop的部署教程,将会详细介绍完全分布式并且是高可用模式下的Hbase的部署流程,废话不多说,我们直接开始! 1. 安装准备 部署Hba ...
- django----csrf跨站请求伪造 auth组件 settings源码 importlib模块
目录 importlib模块 csrf跨站请求伪造 form表单发送 ajax发送 csrf装饰器 auth模块 如何创建超级用户(root) 创建用户 校验用户名和密码是否正确 保存用户登录状态 判 ...
- WinForm WebBrowser 设置cookie
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)] public static exte ...
- AE单词备忘
类的基本特性内 approved 已批准 implemented 已实施 mandatory 强制性的 proposed 偍仪的 validated 已验证
- JS---DOM---为元素解绑事件
解绑事件 注意:用什么方式绑定事件, 就应该用对应的方式解绑事件 1.解绑事件 对象.on事件名字=事件处理函数--->绑定事件 对象.on事件名字=null; //1 对象.on事件名字= ...
- iOS底层实现原理【高级进阶】
想要进阶,想要提升自己一个更高档次,想要拥有更高比格的iOS开发攻城狮们,请关注 ↓↓↓ 我的简书:https://www.jianshu.com/u/3adf2f8593b8 我的掘金:https: ...
- CentOS 磁盘在线扩容
场景介绍: 操作系统Centos7.x 系统有一块vdisk,容量为20G,共分为3个区(swap和boot分区为标准分区xfs文件系统,根分区为LVM分区,xfs文件系统) 业务需求:在VM系统不关 ...
- DFA敏感词过滤实现
package test.java.com.odianyun.util.sensi; import java.util.*; /** * 敏感词处理工具 - DFA算法实现 * * @author s ...
- 关于Redis 二进制内容的 可视化尝试
二进制内容的 能否可视化? 网上的资料比较少啊! -------------------------------------------------------------------------- ...
- Key Management: Hardcoded Encryption key 密钥管理:硬编码加密密钥