1、HashMap是什么?

  HashMap是java常用来存储键值对的数据结构,它是以key/value的形式存储的,它不是线程安全的,Key可以为null值。

2、HashMap的实现原理

  HashMap的底层实现主要是基于数组和链表实现的,HashMap中以通过key值的HashCode值来计算Hash值的,通过Hash值来决定存储在数组的位置,也就是说将新元素插入到数组的这个位置来。当插入新元素时,如果新元素的Hash值与数组中这个位置上元素的Hash值相等,就会出现Hash冲突,那么就会将新元素的next指向数组中的这个位置的元素,新元素就插入到这个位置来。

  结构图:

3、自己编写HashMap类

 Map接口
1 public interface Map{              
int size;                  
boolean isEmpty();            
Object get(Object key);
Object put(Object key,Object value);
interface Node{
Object getKey();
Object getValue();
}
}

实现HashMap类

public class HashMap implements Map{
publci final int DEFAULT_CPACITY=16;      //数组默认容量
private int size=0;
Node[] node =new Node[DEFAULT_CPACITY];
public int size(){
return size;
} public boolean isEmpty(){
return size==0;
} public Object get(Object key){
int keyHashCode=hash(key);
int keyIndex=indexOf(keyHashCode,node.length);
for(Nodes eNode=node[keyIndex];eNode!=null;eNode=eNode.next){
if(eNode.hashValue==keyHashCode&&eNode.key==key)
return eNode.value;
}
return null;
} public Object put(Object key,Object value){
int keyHashCode=hash(key);                //获得key的Hash值
int keyIndex=indexOf(keyHashCode,node.length);    //通过Hash值获得key在数组中的位置
for(Nodes eNode=node[keyIndex];eNode!=null;eNode=eNode.next){        //遍历key位置下的所有node结点,如果找到了新value替换旧value,并返回旧value
if(eNode.hash==keyHashCode&&(eNode.key==key||eNode.key.equals(key))){
Object oldObj=eNode.value;
eNode.value=eNode.value;
return oldObj;
}
}
addEntry(key,value,keyHashCode,keyIndex);       //如果没有找到与key对应的结点,就在链表头新增此结点
return null;
}    /*在链表头新增结点*/
   /*如果超过了原始数组大小,则扩大数组*/
public void addEntry(Object key,Object value,int keyHashCode,int keyIndex){
if(++size==node.length){
resize(2*node.length)
}
Node nodeNext=node[keyIndex];
node[keyIndex]=new Node(keyHashCode,key,value,nodeNext);
}
void resize(int newCapacity) {
Node[] oldNode = node;
int oldCapacity = oldNode.length; Node[] newNode = new Node[newCapacity];
transfer(newNode, initHashSeedAsNeeded(newCapacity));
node= newNode;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}
void transfer(Node[] newTable, boolean rehash) {
int newCapacity = newTable.length;
     //for循环中的代码,逐个遍历链表,重新计算索引位置,将老数组数据复制到新数组中去(数组不存储实际数据,所以仅仅是拷贝引用而已)
for (Node e : node) {
while(null != e) {
Node next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
          //将当前entry的next链指向新的索引位置,newTable[i]有可能为空,有可能也是个entry链,如果是entry链,直接在链表头部插入。
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
} public int indexOf(int keyHashCode,int length){
return keyHashCode%length;
} public int hash(Object key){
return key.hashCode();
} static class Nodes impletents Map.Node{
Object key;
Object value;
int hash;
Nodes next;
public Nodes(int hash,Object key,Objectvalue,Nodes next){
this.hash=hash;
this.key=key;
this.value=value;
this.next=next;
}
public Object getKey(){
return this.key;
}
public Object getValue(){
return this.value;
}
}

总结:

  实现原理就是数组和链表的结合,数组中存放的是这一组HashCode值最新的一个结点,通过这个结点,以链表的形式存放不同的key值的结点。

  在这里简述一下实现步骤:

    1:先写好Map接口,表明HashMap中要做的事,声明结点node接口;

    2:编写HashMap类实现Map接口;

    3:声明结点数组,并实现get和put方法(这里只实现了put和get方法),首先根据Key的值获得key对应的HashCode值,再根据HashCode值找到在数组中的下标,这个位置就是保存所有HashCode值为这个值的首结点,也就是链表头。

    4:实现get方法,通过链表头一个个遍历打到对应的key,并返回对应value,如果没有对应key,则返回空。

    5:实现put方法,也是先遍历链表,如果存在对应的key,则新值替换旧值并返回旧值。如果不存在,则添加新值到链表头(单向链表添加节点最快的方式),在添加节点之前如果size达到了临界值,就需要对数组进行扩容(新建一个数组,并将所有数据拷贝到新数组,如果数组进行扩容,数组长度发生变化,而存储位置 index = hashCode%node.length,index也可能会发生变化,需要重新计算index)。

    其它属性和方法也都是通过这种获得链表头,遍历链表的形式进行的。

如果想要看更加详细的HashMap的原理,可参照博客:http://www.cnblogs.com/chengxiao/p/6059914.html#t3

HashMap原理以及自己实现HashMap的更多相关文章

  1. HashMap原理与优化

    参考文献: HashMap的工作原理 java中HashMap重要性质和优化总结 一.HashMap的基本了解 基本定义:根据源代码的描述可知,HashMap是基于哈希表的Map接口的实现,其包含了M ...

  2. HashMap原理阅读

    前言 还是需要从头阅读下HashMap的源码.目标在于更好的理解HashMap的用法,学习更精炼的编码规范,以及应对面试. 它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而 ...

  3. 面试必问---HashMap原理分析

    一.HashMap的原理 众所周知,HashMap是用来存储Key-Value键值对的一种集合,这个键值对也叫做Entry,而每个Entry都是存储在数组当中,因此这个数组就是HashMap的主干.H ...

  4. Hash存储机制 - HashMap原理 HashSet原理

    HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...

  5. 三.HashMap原理及实现学习总结

    HashMap是Java中最常用的集合类框架之一,是Java语言中非常典型的数据结构.本篇主要是从HashMap的工作原理,数据结构分析,HashMap存储和读取几个方面对其进行学习总结.关于Hash ...

  6. ==和equasl、hashmap原理(***)

    public class String01 { public static void main(String[] args) { String a="test"; String b ...

  7. Java基础-hashMap原理剖析

    Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...

  8. java的HashMap 原理

    https://www.cnblogs.com/chengxiao/p/6059914.html 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比 ...

  9. HashMap底层实现原理以及HashMap与HashTable区别以及HashMap与HashSet区别

    ①HashMap的工作原理 HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象.当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算h ...

随机推荐

  1. 09-----JS事件流的概念(重点)

    在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 时间的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以 ...

  2. jquery——下载、使用

    jQuery是目前使用最广泛的javascript函数库. 怎样安装? 这是下载地址:https://code.jquery.com/ minified是压缩版的 新建一个网页打开上面这个网址,ctr ...

  3. web 中防止sql注入

    public class SqlInject:Page { //检测到注入后的处理方式: 0:仅警告:1:警告+记录:2:警告+自定义错误页面:3:警告+记录+自定义错误页面 ; private co ...

  4. strcpy、strncpy、strlen、memcpy、memset、strcat、strncat、strcmp、strncmp,strchr

    1.strcpy #include<stdio.h> #include<assert.h> char *mystrcpy(char *dest, const char *src ...

  5. Fence Repair (二叉树求解)(优先队列,先取出小的)

    题目链接:http://poj.org/problem?id=3253 Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  6. Bellman_Ford算法(求一个点到任意一点的最短距离)

    单源最短路问题是固定一个起点,求它到任意一点最短路的问题. 记从起点出发到顶点 i 的最短距离为d[i],则有以下等式成立 d[i]=min{d[j]+(从j到 i 的边的权值) 看代码 #inclu ...

  7. Java面向对象_多态性、instanceof关键字

    一.多态 分类:方法的重载与重写:对象的多态性 对象的多态性:向上转型:将子类实例转为父类实例   格式:父类 父类对象=子类实例;是自动转换 向下转型:将父类实例转为子类实例   格式:子类 子类对 ...

  8. ASP.NET Core模块化前后端分离快速开发框架介绍之4、模块化实现思路

    源码 GitHub:https://github.com/iamoldli/NetModular 演示地址 地址:https://nm.iamoldli.com 账户:admin 密码:admin 前 ...

  9. 新浪php面试题

    1. echo count("abc"); 输出什么?答:"1" count — 计算数组中的单元数目或对象中的属性个数int count ( mixed $v ...

  10. Centos6.8 Mysql5.6 安装配置教程

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品.MySQL 最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS ...