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. redis 有序集合

    添加 zadd keyword 0 'eric' 0 'zhang' 0 'yun' 查看列表   zrevrange 降序排列   zrevrange keyword 0 -1 增加分数 zincr ...

  2. Centos7 用gogs搭建git仓库

    0.安装步骤 先安装依赖,然后创建数据库,创建git用户,安装Gogs软件,设置启动,访问web界面进行配置 一.Gogs依赖环境 安装Gogs之前需要配置相应的依赖环境,官网介绍的依赖环境如下: 数 ...

  3. 学习WCF之路,长期更新

    我学习WCF之路:创建一个简单的WCF程序   为了使读者对基于WCF的编程模型有一个直观的映像,我将带领读者一步一步地创建一个完整的WCF应用.本应用功能虽然简单,但它涵盖了一个完整WCF应用的基本 ...

  4. Python 进阶篇

    作者:武沛齐 出处:http://www.cnblogs.com/wupeiqi/articles/5246483.html Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这 ...

  5. k路归并

    public static int[] k_merge(ArrayList<int[]> k_array) { if(CollectionUtils.isEmpty(k_array)){ ...

  6. [转载]Oracle之单引号与双引号

    一.单引号 1.引用一个字符串常量,也就是界定一个字符串的开始和结束 select * from t_sys_user where id='15'; --查询id为15的字符 select * fro ...

  7. mysql 函数GROUP_CONCAT(temp.amount SEPARATOR ',')的用法

    mysql 函数GROUP_CONCAT(temp.amount SEPARATOR ',')的用法 使用场景:例如:想要查询用户的最喜欢购买的几种商品,这个时候就需要使用group_concat(字 ...

  8. java 使用面向对象方式实现录入学生信息,取出成绩最大值、最小值、平均值、对其进行排序

    题目: java 使用面向对象方式实现录入学生信息,取出成绩最大值.最小值.平均值.对其进行排序 gitup源码下载地址: https://github.com/benxiaohai8888/Java ...

  9. 扇形导航 css3

    本篇文章将通过对css3中的2d变化以及过渡进行分析设计 先放上最终效果图                 功能实现:1.给扇形home元素设置点击事件并添加2d旋转 2.给导航栏设置2d旋转 并通过 ...

  10. Java中遍历Set集合的方法

    对 set 的遍历 1.迭代遍历: Set<String> set = new HashSet<String>(); Iterator<String> it = s ...