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. The Little Prince-12/13

    The Little Prince-12/13 突然发现:这应该是一封情书~ 我那时什么也不懂!我应该根据她的行为,而不是根据她的话来判断她. 她使我的生活芬芳多彩,我真不该离开她跑出来.我本应该猜出 ...

  2. SOAPUI 案例操作步骤

    1. 构建项目 2. 运行单个请求 3. 构建测试用例 4. 接口之间传递参数 5. 运行整个测试用例 构建测试 以天气接口为例: 接口: http://ws.webxml.com.cn/WebSer ...

  3. sqlalchemy 多对多关系

    # -*- coding: utf-8 -*- from sqlalchemy import Column, String, create_engine,ForeignKey,Text,Integer ...

  4. 小程序 canvas实现图片预览,图片保存

    wxml 代码: <view class="result-page"> <canvas bindtap="previewImage" canv ...

  5. thiniphp tp5 使用缓存

    在应用或者模块配置文件中配置好所用缓存的类型及相关参数: 如果是文件类型可以用 'cache' => [ 'type' => 'File', 'path' => CACHE_PATH ...

  6. NOIP 2016 天天爱跑步 (luogu 1600 & uoj 261) - 线段树

    题目传送门 传送点I 传送点II 题目大意 (此题目不需要大意,我认为它已经很简洁了) 显然线段树合并(我也不知道哪来这么多显然) 考虑将每条路径拆成两条路径 s -> lca 和 t -> ...

  7. bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...

  8. python --- 25 模块和包

    一.模块 1.导入方式 自己创建的模块名称 切不可和 内置模块的一样 ①  import  模块 ②  import 模块 as  名      设置在此空间的名称 ③  from 模块 import ...

  9. Android O HIDL的实现对接【转】

    本文转载自:https://blog.csdn.net/gh201030460222/article/details/80551897 Android O HIDL的实现对接1. HIDL的定义1.1 ...

  10. ZooKeeper单机伪集群搭建与启动

    下载解压 [xiaobai@xiaobai ~]$ tar -zvxf zookeeper-3.4.9.tar.gz 本机ip地址映射 [xiaobai@xiaobai /]$ su - rootPa ...