1. Entry类中需包含键值的hash值,防止resize时的重复计算;
  2. Map容量为2的整幂,可使用位操作取代取余操作提高效率;
  3. resize时需要将原table的桶内数据置null,利于垃圾回收;
  4. hash函数考虑数据高位的影响,可减少冲突。
 public class MyHashMap<K, V> implements IMap<K, V> {
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int DEFAULT_CAPACITY = 16; Entry<K, V>[] table;
int size;
/**
* 装载因子
*/
float loadFactor;
/**
* 实际的容量
*/
int threshold; public MyHashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
this.threshold = (int) (DEFAULT_CAPACITY * loadFactor);
table = new Entry[DEFAULT_CAPACITY];
} public MyHashMap(int initialCapacity, float loadFactor) {
/**
* 缺少参数检查
*/
int capacity = 1;
while (capacity < initialCapacity) {
capacity <<= 1;
}
this.loadFactor = loadFactor;
this.threshold = (int) (capacity * loadFactor);
table = new Entry[capacity];
} public MyHashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
} /**
* 算术右移,计入高位影响
*/
static int hash(int h) {
return h ^ (h >>> 20) ^ (h >>> 12) ^ (h >>> 7) ^ (h >>> 4);
} @Override
public V put(K k, V v) {
if (k == null) {
putForNull(v);
}
int hash = hash(k.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K, V> e = table[i]; e != null; e = e.next) {
if (e.key.hashCode() == k.hashCode()
&& (e.key == k || (k != null && k.equals(e.key)))) {
V oldValue = e.value;
e.value = v;
return oldValue;
}
}
addEntry(k, v, i);
return null;
} private void addEntry(K k, V v, int index) {
Entry<K, V> e = new Entry<K, V>(k, v, table[index]);
table[index] = e;
if (size++ > threshold) {
resize(table.length * 2);
}
} void resize(int newCapacity) {
Entry[] newTable = new Entry[newCapacity];
transfer(newTable);
table = newTable;
threshold = (int) (newCapacity * loadFactor);
System.out.println("resize()" + " current capacity: " + table.length);
} void transfer(Entry[] newTable) {
for (int i = 0; i < table.length; i++) {
Entry<K, V> e = table[i];
if (e != null) {
/**
* 需要將原table置为空,方可释放内存
*/
table[i] = null;
do {
Entry<K, V> next = e.next;
/**
* 重复计算hash值,效率不高
*/
int index = indexFor(hash(e.key.hashCode()),
newTable.length);
e.next = newTable[index];
newTable[index] = e;
e = next;
} while (e != null);
}
}
} private V putForNull(V value) {
// 未实现
return value;
} /**
* 用位操作取代取余操作,前提是数组长度为2的幂次
*/
private int indexFor(int hash, int length) {
return hash & (length - 1);
} @Override
public V get(K k) {
int hash = hash(k.hashCode());
int index = indexFor(hash, table.length);
Entry<K, V> e = table[index];
while (e != null) {
if (e.key.hashCode() == k.hashCode()
&& (e.key == k || (k != null && k.equals(e.key)))) {
return e.value;
}
e = e.next;
}
return null;
} static class Entry<K, V> {
K key;
V value;
Entry<K, V> next;
int hash; public Entry(K k, V v, Entry<K, V> n) {
key = k;
value = v;
next = n;
// hash = h;
} public V setValue(V v) {
V oldValue = value;
value = v;
return oldValue;
} public boolean equals(Object o) {
if (!(o instanceof MyHashMap.Entry)) {
return false;
}
Entry e = (Entry) o;
Object k1 = e.key;
Object k2 = key;
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = e.value;
Object v2 = value;
if (v1 == v2 || (v1 != v2 && v2.equals(v2))) {
return true;
}
}
return false;
}
}
}

HashMap 实现总结的更多相关文章

  1. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  2. HashMap的工作原理

    HashMap的工作原理   HashMap的工作原理是近年来常见的Java面试题.几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间 ...

  3. 计算机程序的思维逻辑 (40) - 剖析HashMap

    前面两节介绍了ArrayList和LinkedList,它们的一个共同特点是,查找元素的效率都比较低,都需要逐个进行比较,本节介绍HashMap,它的查找效率则要高的多,HashMap是什么?怎么用? ...

  4. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  5. 学习Redis你必须了解的数据结构——HashMap实现

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文链接博客园蜗牛 cnblogs.com\tdws . 首先提供一种获取hashCode的方法,是一种比较受欢迎的方式,该方法参照了一位园友的 ...

  6. HashMap与HashTable的区别

    HashMap和HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的问题不涉及到HashSet和H ...

  7. JDK1.8 HashMap 源码分析

    一.概述 以键值对的形式存储,是基于Map接口的实现,可以接收null的键值,不保证有序(比如插入顺序),存储着Entry(hash, key, value, next)对象. 二.示例 public ...

  8. HashMap 源码解析

    HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...

  9. java面试题——HashMap和Hashtable 的区别

    一.HashMap 和Hashtable 的区别 我们先看2个类的定义 public class Hashtable extends Dictionary implements Map, Clonea ...

  10. 再谈HashMap

    HashMap是一个高效通用的数据结构,它在每一个Java程序中都随处可见.先来介绍些基础知识.你可能也知 道,HashMap使用key的hashCode()和equals()方法来将值划分到不同的桶 ...

随机推荐

  1. Python的dict与set

    一.dict 其他语言中也称为map,使用键-值(key-value)存储 特点: 具有极快的查找速度:可以直接由key计算出value所在的内存地址,而list采用搜索的方式:dict付出的代价是内 ...

  2. async方法:async+await

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. java对redis的基本操作(初识)

    一.server端安装 1.下载 https://github.com/MSOpenTech/redis 可看到当前可下载版本:redis2.6

  4. es6(13)--Promise

    //Promise { //原始方法 let ajax=function(callback){ console.log('执行') setTimeout(function(){ callback&am ...

  5. mysql给查询的结果添加序号

    1.法一: select  (@i:=@i+1)  i,a.url from  base_api_resources a  ,(select   @i:=0)  t2 order by a.id de ...

  6. ROS进阶学习笔记(11)- Turtlebot Navigation and SLAM

    (写在前面: 这里参考rbx书中第八章和ROS社区教程进行学习,先看社区教程) ===  Doing the Turtlebot Navigation   === ref ros wiki: http ...

  7. 调整navigationItem的位置

    UIBarButtonItem *itemTransformView = [[UIBarButtonItem alloc] initWithCustomView:_header.transformVi ...

  8. python tkinter chk

    视频过程中的练习, 可以在python2.7下运行. 001: hello,world: 1 2 3 4 5 6 from Tkinter import Label, Tk root = Tk() t ...

  9. Python入门-随机漫步

    Python入门-随机漫步,贴代码吧,都在代码里面 代码1 class文件 random_walk.py from random import choice class RandomWalk(): # ...

  10. python中的extend

    extend()拓展列表,批量写入 举个例子: 1 a = ["hello", "world", "dlrb"] 2 b = [1, 2, ...