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的底层实现的更多相关文章

  1. 再学Java 之 HashMap的底层实现

    今天参加欢聚时代的面试,我说我自己依靠自己的理解重新实现过HashMap.描述我自己的实现思想后,面试官问“hashmap”底层如果用数组不是效率比较低吗,不是更应该用红黑树吗?我一下子就蒙了.用数组 ...

  2. Java SE LinkedList的底层实现

    关于实现链表的底层原理 链表便于增删,不便于查询 package com.littlepage.linkedList; /** * 基于底层实现LinkedList * @author Littlep ...

  3. java.util.HashMap的简单介绍

    1. java.util.HashMap的底层实现是数组+链表. 2. 简介put(key, value)方法的执行过程: 1)通过key值,使用散列算法计算出来一个hash值,用来确定该元素需要存储 ...

  4. 深入解析Java对象的hashCode和hashCode在HashMap的底层数据结构的应用

    转自:http://kakajw.iteye.com/blog/935226 一.java对象的比较 等号(==): 对比对象实例的内存地址(也即对象实例的ID),来判断是否是同一对象实例:又可以说是 ...

  5. [转]java 的HashMap底层数据结构

    java 的HashMap底层数据结构   HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-v ...

  6. java 的HashMap底层数据结构

    HashMap也是我们使用非常多的Collection,它是基于哈希表的 Map 接口的实现,以key-value的形式存在.在HashMap中,key-value总是会当做一个整体来处理,系统会根据 ...

  7. Java中HashMap底层实现原理(JDK1.8)源码分析

    这几天学习了HashMap的底层实现,但是发现好几个版本的,代码不一,而且看了Android包的HashMap和JDK中的HashMap的也不是一样,原来他们没有指定JDK版本,很多文章都是旧版本JD ...

  8. Java中HashMap底层原理源码分析

    在介绍HashMap的同时,我会把它和HashTable以及ConcurrentHashMap的区别也说一下,不过本文主要是介绍HashMap,其实它们的原理差不多,都是数组加链表的形式存储数据,另外 ...

  9. Java SE 6 新特性: 对脚本语言的支持

    2006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马).跟 Tiger(Java SE 5)相比,Musta ...

随机推荐

  1. 如何获取STM32 MCU的唯一ID及应用(转)

    源: 如何获取STM32 MCU的唯一ID

  2. django创建ORM模型、通过ORM模型操作单个表、ORM模型常用字段

    一.ORM简介 ORM ,全称Object Relational Mapping,中文叫做对象关系映射,通过ORM我们可以通过类的方式去操作数据库,而不用再写原生的SQL语句.通过把表映射成类,把行作 ...

  3. keepalived与zookeeper

    keepalived与zookeeper都可以用来实现高可用,高可用一般跟负载均衡会一起考虑,所以通常也会考虑到相应的负载均衡能力, 1.概括对比: 1.1.Keepalived: 优点:简单,基本不 ...

  4. collectd 检测cpu使用率

    环境配置 1. install epel https://www.cyberciti.biz/faq/installing-rhel-epel-repo-on-centos-redhat-7-x/ 2 ...

  5. shell实现每天0点备份mysql数据库

    就两个文件, 本人学识尚浅,不解释,怕大佬喷. back.sh #/bin/bash MYSQLUSER=root MYSQLPWD=lizhenghua DATABASES=zskdb MYSQLD ...

  6. mysqladmin 使用

    1.第一次没有密码 mysqladmin -u root -p password aook 2.已经有密码的情况下 mysqladmin -u root -paook password aook**0 ...

  7. Flutter学习指南:UI布局和控件

    Flutter学习指南:UI布局和控件 - IT程序猿  https://www.itcodemonkey.com/article/11041.html

  8. linux下关于mysql的命令的用法

    所有关于mysql的命令都在/usr/bin/中, 使用 /usr/bin | grep 'mysql'可以列出这些mysql命令 导出数据库, 可以直接在 命令行中, 使用 mysqldump -u ...

  9. L2-001:dijskstra + 多条最短路径 + 记录中间路径

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840 思路: dijkstra算出最短路 ...

  10. 【做题】TCSRM591 Div1 500 PyramidSequences——数形结合&思维

    题意:定义高度为\(x\)的金字塔数列为周期为\(2x-2\)的无限数列.它的每一个周期都是形如\(1,2,...,x-1,x,x-1,...,2\)的形式.记高度为\(x\)的金字塔数列第\(i\) ...