HashMap原理以及自己实现HashMap
1、HashMap是什么?
HashMap是java常用来存储键值对的数据结构,它是以key/value的形式存储的,它不是线程安全的,Key可以为null值。
2、HashMap的实现原理
HashMap的底层实现主要是基于数组和链表实现的,HashMap中以通过key值的HashCode值来计算Hash值的,通过Hash值来决定存储在数组的位置,也就是说将新元素插入到数组的这个位置来。当插入新元素时,如果新元素的Hash值与数组中这个位置上元素的Hash值相等,就会出现Hash冲突,那么就会将新元素的next指向数组中的这个位置的元素,新元素就插入到这个位置来。
结构图:

3、自己编写HashMap类
Map接口
1 public interface Map{
int size;
boolean isEmpty();
Object get(Object key);
Object put(Object key,Object value);
interface Node{
Object getKey();
Object getValue();
}
}
实现HashMap类
public class HashMap implements Map{
publci final int DEFAULT_CPACITY=16; //数组默认容量
private int size=0;
Node[] node =new Node[DEFAULT_CPACITY];
public int size(){
return size;
}
public boolean isEmpty(){
return size==0;
}
public Object get(Object key){
int keyHashCode=hash(key);
int keyIndex=indexOf(keyHashCode,node.length);
for(Nodes eNode=node[keyIndex];eNode!=null;eNode=eNode.next){
if(eNode.hashValue==keyHashCode&&eNode.key==key)
return eNode.value;
}
return null;
}
public Object put(Object key,Object value){
int keyHashCode=hash(key); //获得key的Hash值
int keyIndex=indexOf(keyHashCode,node.length); //通过Hash值获得key在数组中的位置
for(Nodes eNode=node[keyIndex];eNode!=null;eNode=eNode.next){ //遍历key位置下的所有node结点,如果找到了新value替换旧value,并返回旧value
if(eNode.hash==keyHashCode&&(eNode.key==key||eNode.key.equals(key))){
Object oldObj=eNode.value;
eNode.value=eNode.value;
return oldObj;
}
}
addEntry(key,value,keyHashCode,keyIndex); //如果没有找到与key对应的结点,就在链表头新增此结点
return null;
}
/*在链表头新增结点*/
/*如果超过了原始数组大小,则扩大数组*/
public void addEntry(Object key,Object value,int keyHashCode,int keyIndex){
if(++size==node.length){
resize(2*node.length)
}
Node nodeNext=node[keyIndex];
node[keyIndex]=new Node(keyHashCode,key,value,nodeNext);
}
void resize(int newCapacity) {
Node[] oldNode = node;
int oldCapacity = oldNode.length;
Node[] newNode = new Node[newCapacity];
transfer(newNode, initHashSeedAsNeeded(newCapacity));
node= newNode;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
void transfer(Node[] newTable, boolean rehash) {
int newCapacity = newTable.length;
//for循环中的代码,逐个遍历链表,重新计算索引位置,将老数组数据复制到新数组中去(数组不存储实际数据,所以仅仅是拷贝引用而已)
for (Node e : node) {
while(null != e) {
Node next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
//将当前entry的next链指向新的索引位置,newTable[i]有可能为空,有可能也是个entry链,如果是entry链,直接在链表头部插入。
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
public int indexOf(int keyHashCode,int length){
return keyHashCode%length;
}
public int hash(Object key){
return key.hashCode();
}
static class Nodes impletents Map.Node{
Object key;
Object value;
int hash;
Nodes next;
public Nodes(int hash,Object key,Objectvalue,Nodes next){
this.hash=hash;
this.key=key;
this.value=value;
this.next=next;
}
public Object getKey(){
return this.key;
}
public Object getValue(){
return this.value;
}
}
总结:
实现原理就是数组和链表的结合,数组中存放的是这一组HashCode值最新的一个结点,通过这个结点,以链表的形式存放不同的key值的结点。
在这里简述一下实现步骤:
1:先写好Map接口,表明HashMap中要做的事,声明结点node接口;
2:编写HashMap类实现Map接口;
3:声明结点数组,并实现get和put方法(这里只实现了put和get方法),首先根据Key的值获得key对应的HashCode值,再根据HashCode值找到在数组中的下标,这个位置就是保存所有HashCode值为这个值的首结点,也就是链表头。
4:实现get方法,通过链表头一个个遍历打到对应的key,并返回对应value,如果没有对应key,则返回空。
5:实现put方法,也是先遍历链表,如果存在对应的key,则新值替换旧值并返回旧值。如果不存在,则添加新值到链表头(单向链表添加节点最快的方式),在添加节点之前如果size达到了临界值,就需要对数组进行扩容(新建一个数组,并将所有数据拷贝到新数组,如果数组进行扩容,数组长度发生变化,而存储位置 index = hashCode%node.length,index也可能会发生变化,需要重新计算index)。
其它属性和方法也都是通过这种获得链表头,遍历链表的形式进行的。
如果想要看更加详细的HashMap的原理,可参照博客:http://www.cnblogs.com/chengxiao/p/6059914.html#t3
HashMap原理以及自己实现HashMap的更多相关文章
- HashMap原理与优化
参考文献: HashMap的工作原理 java中HashMap重要性质和优化总结 一.HashMap的基本了解 基本定义:根据源代码的描述可知,HashMap是基于哈希表的Map接口的实现,其包含了M ...
- HashMap原理阅读
前言 还是需要从头阅读下HashMap的源码.目标在于更好的理解HashMap的用法,学习更精炼的编码规范,以及应对面试. 它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而 ...
- 面试必问---HashMap原理分析
一.HashMap的原理 众所周知,HashMap是用来存储Key-Value键值对的一种集合,这个键值对也叫做Entry,而每个Entry都是存储在数组当中,因此这个数组就是HashMap的主干.H ...
- Hash存储机制 - HashMap原理 HashSet原理
HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...
- 三.HashMap原理及实现学习总结
HashMap是Java中最常用的集合类框架之一,是Java语言中非常典型的数据结构.本篇主要是从HashMap的工作原理,数据结构分析,HashMap存储和读取几个方面对其进行学习总结.关于Hash ...
- ==和equasl、hashmap原理(***)
public class String01 { public static void main(String[] args) { String a="test"; String b ...
- Java基础-hashMap原理剖析
Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...
- java的HashMap 原理
https://www.cnblogs.com/chengxiao/p/6059914.html 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比 ...
- HashMap底层实现原理以及HashMap与HashTable区别以及HashMap与HashSet区别
①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...
随机推荐
- 033 Search in Rotated Sorted Array 搜索旋转排序数组
假设按照升序排序的数组在预先未知的某个关键点上旋转.(即 0 1 2 4 5 6 7 将变成 4 5 6 7 0 1 2).给你一个目标值来搜索,如果数组中存在这个数则返回它的索引,否则返回 -1.你 ...
- 强连通图 Tarjan算法
算法学习:https://blog.csdn.net/qq_16234613/article/details/77431043 http://www.cnblogs.com/chenchengxun/ ...
- Unity [Tooltip("")]
把Ad2Controller脚本挂在Ad2Ad3Manager游戏对象上,在非运行状态下把鼠标放在inspector的AdButtonObj2上就会显示广告2按钮. 如下图:
- 【Unity3D】用继承EditorUpdater类来实现Editor模式下的后台处理
EditorWindow类的OnGUI函数只会在窗口焦点处于Editor窗口上的时候才会运行.如果希望焦点不在Editor窗口上的时候,它也能实时更新,可以实现以下方法: OnDestroy OnDe ...
- SpringBoot | 第十一章:Redis的集成和简单使用
前言 上几节讲了利用Mybatis-Plus这个第三方的ORM框架进行数据库访问,在实际工作中,在存储一些非结构化或者缓存一些临时数据及热点数据时,一般上都会用上mongodb和redis进行这方面的 ...
- net start命令发生系统错误5和错误1058的解决方法
net start命令用于开启服务,格式为:net start [服务名](与之对应的"net stop [服务名]"为关闭服务命令) 5是没有管理员权限,右键管理员即可 1058 ...
- nodejs 实践:express 最佳实践系列
nodejs 实践:express 最佳实践系列 nodejs 实践:express 最佳实践(一) 项目结构 nodejs 实践:express 最佳实践(二) 中间件 nodejs 实践:expr ...
- tomcat7 开机自启动(转)
转自 http://blog.csdn.net/rainyspring4540/article/details/51861079 环境:win7 tomcat7 开机自启动: 使用管理员打开命令提示 ...
- CF1182E Product Oriented Recurrence
思路: fn = can * f1xn * f2yn * f3zn, 首先dp计算指数部分an = an-1 + an-2 + an-3 + 2 * n - 6, 而an-1 = an-2 + an- ...
- (已解决)Arduino mega2560 R3插在电脑上没有反应
OK,话不多说.网上找了一些资料,感觉都说的不够清晰.自己琢磨了下,有了一个简单粗暴的方法. 步骤1:插上Arduino mega2560板子.没有反应. 步骤2:我的电脑-管理-设备管 ...