public class MyHashMap<K, V> {
private class Entry<K, V> {
int hash;
K key;
V value;
Entry<K, V> next; Entry(int hash, K key, V value, Entry<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
} private static final int DEFAULT_CAPACITY = 1 << 2; private Entry<K, V>[] table; private int capacity; private int size; private final float loadFactor = 0.75f; public MyHashMap() {
this(DEFAULT_CAPACITY);
} @SuppressWarnings("unchecked")
public MyHashMap(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException();
} else {
table = new Entry[capacity];
size = 0;
this.capacity = capacity;
}
} public int size() {
return size;
} public boolean isEmpty() {
return size == 0 ? true : false;
} public V put(K key, V value) {
if (key == null) {
throw new RuntimeException("key不可以为空!");
}
if (size >= capacity * loadFactor) {
// 开始rehash
resize(2 * table.length);
int hash = (null != key) ? hash(key) : 0;
int index = indexFor(hash, table.length);// 注意此时的table已经扩容了
}
V newValue = putEntry(key, value);
return newValue;
} @SuppressWarnings({ "rawtypes", "unchecked" })
private void resize(int newCapacity) {
System.out.println("我们要扩容了!!当前的size是:" + size);
// 让数组长度乘以两倍
Entry[] newTable = new Entry[newCapacity];
transfer(newTable, true);
table = newTable;
} @SuppressWarnings({ "rawtypes", "unchecked" })
private void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K, V> e : table) {
while (e != null) {
if (rehash) {
// 要重新hash
e.hash = null == e.key ? 0 : hash(e.key);
}
int index = indexFor(e.hash, newCapacity);
// 开始把e放进新的数组中
// 注意,每次插入新的值都必须要插在散列链表的头部
e.next = newTable[index];
newTable[index] = e;
e = e.next;
}
}
} private V putEntry(K key, V value) {
if (key == null) {
throw new RuntimeException("key不可以为空!");
}
int hash = hash(key);
int i = indexFor(hash, table.length);
Entry<K, V> newEn = new Entry<K, V>(hash, key, value, null);
for (Entry<K, V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
// 代表当前的e和要添加的key冲突了,那么就覆盖
V oldValue = e.value;
e.value = value;// 当前的e的value要替换为新的value
return oldValue;
}
}
// 如果上面没有找到的话,就要往链表添加元素了
size++;
addEntry(newEn, i);
return value;
} private void addEntry(Entry<K, V> entry, int index) {
Entry<K, V> e = table[index];
table[index] = entry;
entry.next = e;
} public V get(K key) {
if (key == null) {
throw new RuntimeException("key不可以为空!");
}
Entry<K, V> entry = getEntry(key);
return null == entry ? null : entry.value;
} private Entry<K, V> getEntry(K key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
for (Entry<K, V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
return e;
}
}
return null;
} public V remove(K key) {
Entry<K, V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
} private Entry<K, V> removeEntryForKey(K key) {
if (size == 0) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
Entry<K, V> cur = table[i];
Entry<K, V> e = cur;
while (e != null) {
if (e.hash == hash && (e.key == key || key.equals(e.key))) {
size--;
// 如果删除的是prev的话
if (cur == e) {
table[i] = e.next;
} else {
// 就让cur的next等于e的next
cur.next = e.next;
}
return e;
}
cur = e;
e = e.next;
}
return null;
} private int indexFor(int hash, int length) {
return hash & (length - 1);// 哈希值和长度减一做与运算
} private int hash(K key) {
return key.hashCode();
} public static void main(String[] args) {
MyHashMap<Integer, String> map = new MyHashMap<>();
}
}

  

HashMap原理及简单实现的更多相关文章

  1. Java 7 和 Java 8 中的 HashMap原理解析

    HashMap 可能是面试的时候必问的题目了,面试官为什么都偏爱拿这个问应聘者?因为 HashMap 它的设计结构和原理比较有意思,它既可以考初学者对 Java 集合的了解又可以深度的发现应聘者的数据 ...

  2. Java注解的基本概念和原理及其简单实用

      一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析 ...

  3. HashMap原理(二) 扩容机制及存取原理

    我们在上一个章节<HashMap原理(一) 概念和底层架构>中讲解了HashMap的存储数据结构以及常用的概念及变量,包括capacity容量,threshold变量和loadFactor ...

  4. HashSet的实现原理,简单易懂

    HashSet的实现原理,简单易懂   答: HashSet实际上是一个HashMap实例,都是一个存放链表的数组.它不保证存储元素的迭代顺序:此类允许使用null元素.HashSet中不允许有重复元 ...

  5. Java 实现《编译原理》简单-语法分析功能-LL(1)文法 - 程序解析

    Java 实现<编译原理>简单-语法分析功能-LL(1)文法 - 程序解析 编译原理学习,语法分析程序设计 (一)要求及功能 已知 LL(1) 文法为: G'[E]: E→TE' E'→+ ...

  6. java中HashMap原理?

    参考:https://www.cnblogs.com/yuanblog/p/4441017.html(推荐) https://blog.csdn.net/a745233700/article/deta ...

  7. HBase笔记:对HBase原理的简单理解

    早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...

  8. 编译原理(简单自动词法分析器LEX)

    编译原理(简单自动词法分析器LEX)源程序下载地址:  http://files.cnblogs.com/files/hujunzheng/%E6%B1%87%E7%BC%96%E5%8E%9F%E7 ...

  9. Optaplanner规划引擎的工作原理及简单示例(2)

    开篇 在前面一篇关于规划引擎Optapalnner的文章里(Optaplanner规划引擎的工作原理及简单示例(1)),老农介绍了应用Optaplanner过程中需要掌握的一些基本概念,这些概念有且于 ...

随机推荐

  1. git推送新项目到github

    1.首先在github上新建一个裸仓库 得到新仓库地址 2.打开本地要添加项目的目录,右键选择git bash,执行命令 (1)git init (2)git remote add origin ht ...

  2. python 安装 colorama 控制台输出彩色文字

    pip install colorama from colorama import Back,Fore,Style # 字体颜色print(Fore.LIGHTBLUE_EX,'HelloWorLd' ...

  3. Linux学习大纲(高人整理)

    1.Linux初级 1.1 OS操作系统的原理 1.2 了解常用命令 开机关机 时间管理:date cal clock 1.3 目的结构.目的管理 树形结构 tree cd 1.4 文件管理.文件查找 ...

  4. url简单加密

    使用urlencode和urldecode可以对传输的字符串进行简单的加密,也可用于将汉字转换为16进制数字进行传输,每个16进制数前面都带一个% urlencode : 将中文转换为16进制数 ur ...

  5. python网络爬虫(1)静态网页抓取

    获取响应内容: import requests r=requests.get('http://www.santostang.com/') print(r.encoding) print(r.statu ...

  6. centos:mysql主从同步配置(2018)

    centos:mysql主从同步配置(2018) https://blog.csdn.net/liubo_2016/article/details/82379115 主服务器:10.1.1.144; ...

  7. JS作用域及域解析规则

    1.JS作用域:变量和函数作用的范围. 2.JS解析器可以分为域解析和逐行解读代码两个过程. 域解析:1.当进行域解析的时候,一旦找到var,就会提取后面的变量名,并给它赋值给undefined. 2 ...

  8. CDH配置YARN动态资源分配

    场景:根据不同项目或不同用户,对yarn资源队列进行划分,达到资源管控,任务管控的目的 yarn资源队列参数设置 当设置为 true 时,如果未指定池名称,Fair Scheduler 将会使用用户名 ...

  9. ArrayList知识详解

    简介 ArrayList是Java集合常用的数据结构之一,继承自AbstractList,实现了List,RandomAccess.Cloneable.Serializable等一系列接口,支持快速访 ...

  10. nginx的服务架构

    nginx服务架构 模块 习惯上将nginx的模块分成核心模块,HTTP模块,邮件模块,以及第三方模块 核心模块主要包含两类功能的支持,一类是主体功能,包括进程管理,权限管理错误日志解析,配置解析:另 ...