Java SE HashMap的底层实现
1.hash散列算法
由于hashmap在存储过程中是数组加链表的存储过程,所以定义数组长度为16(建议是2的n次幂的长度),之后进行每个数组的地址都指向一个链表进行存储

hash表算法可对数组长度length取余,如果length是2的n次幂,则可对length-1取位运算&
例如,任意长度8是2的3次幂,随机的int值对8取余,和对7进行&运算得到的结果是一样的
int a=;
System.out.println(a%);
System.out.println(a&);
在jdk 7之前的源码中,则对hash凑得进行了2次散列处理,为了使散列更均匀

在jdk 8往后,数组长度大于8时,链表转换为红黑树,大大提高了查找速率
2.手工实现hashMap
取数据
1.首先通过key计算hashcode来得到数组的存储,再通过next便利链表进行查找比较,直到返回true的节点对象为止
2.Java中有规定,两个内容相同的(调用equals方法值为true的)对象必须有想等的hashcode,如果两个对象内容相等,而hashcode的值不一样,则会产生悖论
扩容问题
1.jdk7之前
hashMap的位桶数组,初始大小为16,实际使用时,大小可变,如果位桶数组中元素个数达到(0.75*数组length),就重新调整数组为2倍大小,扩容是个耗时的过程,相当于重新定义数组和链表,进行复制操作
2.jdk8之后
位桶数组初始大小为16,当链表长度大于8时,将链表中各个元素拷贝到红黑树上,大大提高了查找效率
3.源代码
package com.littlepage.HashMap;
/**
* 用于LittlePagesHashMap的Node
* @author LittlePage
*/
public class Node<K,V> {
private int hash;
private K key;
private V value;
private Node<K,V> next; public Node(K key, V value) {
super();
this.key = key;
this.value = value;
} public int getHash() {
return hash;
} public void setHash(int hash) {
this.hash = hash;
} public K getKey() {
return key;
} public void setKey(K key) {
this.key = key;
} public V getValue() {
return value;
} public void setValue(V value) {
this.value = value;
} public Node<K, V> getNext() {
return next;
} public void setNext(Node<K, V> next) {
this.next = next;
} @Override
public String toString() {
return "(" + key + "," + value + ")";
} }
package com.littlepage.HashMap;
public class LittlePagesHashMap<K,V> {
Object[] table=new Node[]; //位桶数组
int size;//存放键值对个数
public LittlePagesHashMap(){
table=new Node[];
}
public void put(K key,V value){
//定义了新的节点对象
Node<K,V> newNode=new Node<>(key,value);
newNode.setHash(myHash(key.hashCode(), table.length));
@SuppressWarnings("unchecked")
Node<K,V> temp=(Node<K, V>) table[newNode.getHash()];
if(temp==null){
table[newNode.getHash()]=newNode;
}else{
while(temp.getNext()!=null){
if(temp.getKey().equals(newNode.getKey())){
temp.setValue(newNode.getValue());
size++;
return;
}
temp=temp.getNext();
}
temp.setNext(newNode);
}
size++;
}
public int myHash(int hashcode,int length){
return hashcode&(length-);
}
@Override
public String toString(){
StringBuilder sb=new StringBuilder();
sb.append("[");
for(int i=;i<table.length;i++){
if(table[i]==null) continue;
else{
@SuppressWarnings("unchecked")
Node<K,V> temp=(Node<K, V>) table[i];
sb.append(temp);
while((temp=temp.getNext())!=null){
sb.append(","+temp);
}
sb.append("]");
}
}
return sb.toString();
}
}
package com.littlepage.HashMap;
public class Test {
public static void main(String[] args) {
LittlePagesHashMap<String, String> a=new LittlePagesHashMap<>();
a.put("a", "gg");
a.put("", "pp");
System.out.println(a);
}
}
Java SE HashMap的底层实现的更多相关文章
- 再学Java 之 HashMap的底层实现
今天参加欢聚时代的面试,我说我自己依靠自己的理解重新实现过HashMap.描述我自己的实现思想后,面试官问“hashmap”底层如果用数组不是效率比较低吗,不是更应该用红黑树吗?我一下子就蒙了.用数组 ...
- Java SE LinkedList的底层实现
关于实现链表的底层原理 链表便于增删,不便于查询 package com.littlepage.linkedList; /** * 基于底层实现LinkedList * @author Littlep ...
- java.util.HashMap的简单介绍
1. java.util.HashMap的底层实现是数组+链表. 2. 简介put(key, value)方法的执行过程: 1)通过key值,使用散列算法计算出来一个hash值,用来确定该元素需要存储 ...
- 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用
转自:http://kakajw.iteye.com/blog/935226 一.java对象的比较 等号(==): 对比对象实例的内存地址(也即对象实例的ID),来判断是否是同一对象实例:又可以说是 ...
- [转]java 的HashMap底层数据结构
java 的HashMap底层数据结构 HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-v ...
- java 的HashMap底层数据结构
HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据 ...
- Java中HashMap底层实现原理(JDK1.8)源码分析
这几天学习了HashMap的底层实现,但是发现好几个版本的,代码不一,而且看了Android包的HashMap和JDK中的HashMap的也不是一样,原来他们没有指定JDK版本,很多文章都是旧版本JD ...
- Java中HashMap底层原理源码分析
在介绍HashMap的同时,我会把它和HashTable以及ConcurrentHashMap的区别也说一下,不过本文主要是介绍HashMap,其实它们的原理差不多,都是数组加链表的形式存储数据,另外 ...
- Java SE 6 新特性: 对脚本语言的支持
2006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马).跟 Tiger(Java SE 5)相比,Musta ...
随机推荐
- @RefreshScope 的作用
让在application.properties里自定义的变量也能通过@Value 注解正常注入
- LogUtil工具
package com.develop.web.util; import java.util.concurrent.locks.ReentrantLock; import org.slf4j.Logg ...
- java提供的线程池的使用
应用场景,比如你有个业务模块,非常耗时,并且还需要重复调用5次. 如果你写个for循环调用5次,调用一次3秒,那么5次就15秒,不是很友好. 这时,如果你用线程池就方便了,多线程跑,都跑完,收集到结果 ...
- django 模型类的常见字段约束,以及filter 过滤和查询
null 不设置时默认设置为False.设置为True时,数据库表字段中将存入NULL的记录. null和blank组合使用,null=True,blank=True,表示该字段可以为空 blank ...
- Golang框架beego电影网爬虫小试牛刀
学习了一段时间golang,又参考课程学习了beego开发网站爬虫,项目的目录结构是: 采集的目标是豆瓣网电影,入口地址是:https://movie.douban.com/subject/19008 ...
- jQuery 表单内容的获取
var formData = $('#myform').serialize()
- 解决c1xx fatal error C1083 Cannot open source file
在项目开发过程中,遇到一个问题,一个工程B导入另外一个工程A的生产代码,出现这个错误,最后查阅资料发现是文件路径太深,导致文件路径字符超过了217字符. 写了一个测试Demo来验证: 一.新建Win3 ...
- VC++使用MapFileAndCheckSum完成自检测
转载:https://blog.csdn.net/lekonpeng/article/details/4150464 当我们完成一个工程,编译成可执行文件后,一般是不希望这个可执行文件被人改动的,那么 ...
- topcoder srm 661 div1
problem1 link $N+1$到$M$ 之间的数字要包含所有1到$N$之间出现的质因子的最高幂即可. problem2 link 从第一个节点到第$N$个节点依次考虑.对于第$i$个节点来说, ...
- Bootstrap3基础 dropdown divider 下拉列表中的分割线
内容 参数 OS Windows 10 x64 browser Firefox 65.0.2 framework Bootstrap 3.3.7 editor ...