简易HashMap实现
为了更好的理解HashMap线程不安全的根源,这里提供了HashMap的简易实现:
package map.test;
import org.apache.commons.lang3.StringUtils; /**
* Author:yepei@meituan.com
* Date:2017/7/5
* Time:15:45
* ------------------------------------
* Desc:
*/
public class HashMp {
private transient Node[] entries;//数组
private transient float loadFactor;
private transient int size; public static void main(String[] args) {
HashMp map = new HashMp(2, 0.75f);
map.put(3, "A");
System.out.println(map);
map.put(5, "B");
map.put(7, "C");
map.put(11, "D");
map.put(9, "E");
map.put(12, "F");
map.put(17, "G");
map.put(22, "H");
map.put(24, "I");
map.put(25, "I");
System.out.println(map); String s1 = map.get(22);
String s2 = map.get(25);
String s3 = map.get(0);
} public HashMp(int capacity, float loadFactor) {
this.entries = new Node[capacity];
this.loadFactor = loadFactor;
} public HashMp() {
this(16, 0.75f);
} public String put(int key, String value) {
Node n = new Node(key, value);
//算Hash值,为简单起见,hash值
int i = n.getIndex(entries.length);
Integer thisKey = key;
//查找是否有重复: hashCode相等,且equals方法相等的
for (Node old = entries[i]; old != null; old = old.next) {
Integer oldKey;
//hash相同,且equals返回true,证明有重复值插入,直接替换掉旧值
if (old.getHash() == n.getHash() && ((oldKey = old.key) == key || thisKey.equals(oldKey))) {
String oldValue = old.value;
old.value = value;//替换成新值
return oldValue;//返回旧值
}
}
//该key不存在,需要增加一个结点
addEntry(n);
return null;
} public String get(int key) {
int idx = new Node(key, null).getIndex(entries.length);
Integer thisKey = key;
//查找是否有重复: hashCode相等,且equals方法相等的
for (Node old = entries[idx]; old != null; old = old.next) {
Integer oldKey = old.key;
if (thisKey == oldKey || thisKey.equals(oldKey)) {
return old.value;
}
}
return null;
} private void addEntry(Node n) {
int oldLen = entries.length;
int targetIdx = n.getIndex(oldLen);
n.next = entries[targetIdx];
entries[targetIdx] = n;//插入到链首
if (size++ >= oldLen * loadFactor) {
resize(2 * oldLen);
}
} private void resize(int newCapacity) {
Node[] old = entries;
Node[] newMap = new Node[newCapacity];
for (int j = 0; j < old.length; j++) {
Node e = old[j];
if (e == null) {
continue;
}
old[j] = null;//老表中的元素置为Null //注意:该过程会将同一个bucket中的元素逆置,因为总是将元素插在了新表的头部。
//但不是就地逆置,因为将元素逐个copy到了新的链表中
do {
Node next = e.next;//暂存尾链表(去掉head的链表)
int i = e.getIndex(newCapacity);//得到将在新表中存储的位置
e.next = newMap[i];//切断指针,重新指向新表的表头(可能为null)
newMap[i] = e;//将e插入到新链表头部
e = next;//重新将e赋值为尾链表的头,对尾链表继续“切断指针,插入新表头”
} while (e != null);
}
entries = newMap;
} @Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
int i = 0;
for (Node n : entries) {
sb.append(i++).append("{").append(n).append("}, ");
}
return StringUtils.removeEnd(sb.toString(), ", ") + "]";
} static class Node {
int key;
String value;
Node next; Node(int key, String value) {
this.key = key;
this.value = value;
} int getIndex(int tableLength) {
return getHash() % tableLength;
} //为方便起见,hash值直接取该对象的key
int getHash() {
return key;
} @Override
public String toString() {
return "(" + key + "," + value + ")——>" + next;
}
}
}
参考
HashMap源码解读:http://www.xiaomager.com/category/program/java/hashmap
Hashcode生成原理:http://www.cnblogs.com/godtrue/p/6395098.html
HashMap存在的三大并发问题:https://my.oschina.net/xianggao/blog/393990
简易HashMap实现的更多相关文章
- HashMap内部结构及实现原理
简单介绍 在研究HashMap之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能 数组:采用一段连续的存储单元来存储数据.对于指定下标的查找,时间复杂度为O(1):通过给定值进行查找,需 ...
- Java面试题之HashMap阿里面试必问知识点,你会吗?
面试官Q1:你用过HashMap,你能跟我说说它的数据结构吗? HashMap作为一种容器类型,无论你是否了解过其内部的实现原理,它的大名已经频频出现在各种互联网Java面试题中了.从基本的使用角度来 ...
- hashmap的简易实现,基本实现PUT GET
p.p1 { margin: 0; font: 12px Menlo; color: rgba(79, 118, 203, 1) } /*简易版的HASHMAP包括基本的GET PUT思想 * 从数 ...
- 【简易版】HashMap(增删改查)
1.HashMap概述 (1)首先HashMap是基于哈希表的Map接口实现的.另外HashMap中存储的数据是按照键值跟键值对的关系来进行存储的. (2)不同于ArrayList方法的是,Array ...
- 自己用HashMap来模拟一个Session缓存(简易版)
本文记录:Hibernate中一级缓存的特点. 一级缓存的细节什么操作会向一 1.级缓存放入数据 save,update,saveOrUpdate,load,get,list,iterate,lock ...
- 实现一个简易的HashMap
实现一个键的类型为int,值的类型为int的HashMap 输入一个T,表示操作次数: 之后每行接一个操作,可以包括插入.删除.修改.查询.清空.判断是否有这个键: 因为是刚学完随手敲的,所以功能粗糙 ...
- 【面向对象版】HashMap(增删改查)
前言: 关于什么是HashMap,HashMap可以用来做些什么,这些定义类的描述,请参照[简易版]HashMap(增删改查)的内容. 这章节主要是面向实例,直接进行HashMap(增删改查)的演示. ...
- Spring + iBatis 的多库横向切分简易解决思路
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- Android学习之路——简易版微信为例(二)
1 概述 从这篇博文开始,正式进入简易版微信的开发.深入学习前,想谈谈个人对Android程序开发一些理解,不一定正确,只是自己的一点想法.Android程序开发不像我们在大学时候写C控制台程序那样, ...
随机推荐
- OVS 内核KEY值提取及匹配流表代码分析
原文链接:http://ry0117.com/2016/12/24/OVS内核KEY值提取及匹配流表代码分析/ 当开启OVS后,创建datapath类型为system的网桥并他添加相关接口,OVS网桥 ...
- series dataframe 的 idxmax()
返回最大值的索引
- 650. 2 Keys Keyboard
Initially on a notepad only one character 'A' is present. You can perform two operations on this not ...
- UIVisualEffectView(高斯模糊效果)
///高斯模糊. UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; tempView. ...
- jzoj5996
我們可以枚舉每一個串的最短回文後綴,這樣一定不會算重. 雖然一個字符串可能會有多個回文後綴,但是答案只會在最短的後綴被計算 記f[i]表示長度為i回文串中,沒有長度>1的回文後綴的個數,將總個數 ...
- Binary Indexed Tree-307. Range Sum Query - Mutable
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...
- 三,mysql优化--sql语句优化之索引一
1,需求:如何在一个项目中,找到慢查询的select,mysql数据库支持把慢查询语句,记录到日志中.供程序员分析.(默认不启用此功能,需要手动启用) 修改my.cnf文件(有些地方是my.ini) ...
- 比特、字节、K
比特(bit) 比特,计算机专业术语,是信息量单位,由英文BIT音译而来.BIT为Binary digit(二进制数)位的缩写.二进制数的一位所包含的信息就是一比特,如二进制数0100就是4比特. 字 ...
- Python小白学习之路(十二)—【前向引用】【风湿理论】
前向引用 风湿理论(函数即变量) 理论总是很抽象,我个人理解: 代码从上到下执行,一旦遇到定义的函数体,内存便为其开辟空间,并用该函数的名字作为一个标识但是该函数体内具体是什么内容,这个时候并不着急去 ...
- django 的ajax 请求,使用form的验证机制。
所有的form都需要在后台验证,前台验证是不可靠的,django的验证是后台验证,前台提示错误信息. js验证是在前台的,无需发送消息给后台,但安全性不可靠,强调的是用户体验. 要求,使用弹出框,弹出 ...