简易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控制台程序那样, ...
随机推荐
- 第三章 CopyOnWriteArrayList源码解析
注:在看这篇文章之前,如果对ArrayList底层不清楚的话,建议先去看看ArrayList源码解析. http://www.cnblogs.com/java-zhao/p/5102342.html ...
- day 59 pymysql
PyMySQL介绍 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PYmysql安装 pip install pymys ...
- Day 48 HTML 语言Day1
HTML文档结构 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&qu ...
- Jmeter-正则表达式提取器获取token-小实例
步骤一:在需要获取token的接口上,添加正则表达式提取器 说明: (1) Apply to:应用范围 Main sample and sub-samples:匹配范围包括当前父取样器并覆盖至子取样器 ...
- 萝卜保卫战3内购破解+Toast窗口增加(Love版)
涉及到一些不同的破解的方法,以及不同的破解思路,还有一些重要权限的删除等. 作者:HAI_ 这次目标是经常玩的萝卜保卫战,不知不觉,已经更新到3了.详细分析请参考https://bbs.ichunqi ...
- centOS7 下安装smb服务器
转载自:http://www.cnblogs.com/lgh344902118/p/7503620.html centOS7和windows10 samba是一款可以让linux和windows下共享 ...
- day 49 数据分析, 数据聚合 F 查询 Q 查询
6.聚合查询和分组查询 1.聚合查询aggregate 我们先通过一个例子来感受一下吧. 1 2 3 # 计算所有图书的平均价格 books = models.Book.objects.aggrega ...
- SQL实现数据行列转换
前言: 在日常的工作中,使用数据库查看数据是很经常的事,数据库的数据非常多,如果此时的数据设计是一行行的设计话,就会有多行同一个用户的数据,查看起来比较费劲,如果数据较多时,不方便查看,为了更加方便工 ...
- 隐型马尔科夫模型(HMM) 简介
先介绍一下马尔科夫模型: 马尔可夫模型(Markov Model)是一种统计模型,广泛应用在语音识别,词性自动标注,音字转换,概率文法等各个自然语言处理等应用领域.经过长期发展,尤其是在语音识别中的成 ...
- 快速初步了解Neo4j与使用
快速初步了解Neo4j与使用 Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化 ...