【java集合】自己实现简易的HashMap~改良
来源:互联网 发布:c 高级编程 第7版 pdf 编辑:程序博客网 时间:2024/06/10 02:14
map接口:
public interface IMyMap<K, V> { V put(K key, V value); V get(K key); int size(); interface Entry<K, V>{};}
实现:
import java.util.HashMap;/** * Created by hasee on 2017/11/2. */public class MyHashMap<K, V> implements IMyMap<K, V> { static final float DEFAULT_LOAD_FACTOR = 0.75f; static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //一定要是2的整数幂 Entry<K, V>[] table; int size; final float loadFactor; int threshold; public MyHashMap() { loadFactor = DEFAULT_LOAD_FACTOR; table = new Entry[DEFAULT_INITIAL_CAPACITY]; threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); } public MyHashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } public MyHashMap(int initialCapacity, float loadFactor) { this.loadFactor = loadFactor; int capacity = 1; while (capacity < initialCapacity) //使得数组长度一定是2的整数幂 capacity <<= 1; threshold = (int)(capacity * loadFactor); table = new Entry[capacity]; } @Override public V put(K key, V value) { int h = hash(key); int index = indexFor(h, table.length); //迭代此索引上的所有Entry对象 for (Entry<K, V> e = table[index]; null!=e; e=e.next){ //如果当前e的hash等于计算出来的hash,并且key也等于e的key,那么替换e的value并返回旧值 if (h == e.hash && key.equals(e.key)){ V oldValue = e.value; e.value = value; return oldValue; } } //如果索引上还没有对象或索引的链表没有此key,就创建对象 Entry<K, V> e = table[index]; table[index] = new Entry<K, V>(e, value, key, h); //检测是否需要扩容 if (size++ >= threshold) doubleSize(); return null; } //哈希扰动函数(提高性能的关键) static final int hash(Object key){// int h;// return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); //上面两行是jdk源码,它等价于下面 if(key == null) return 0; //获取一个32位的hashCode int h = key.hashCode(); //无符号右移16位(左边填充0),即如果当前hashCode小于2的16次方,temp就会等于0 int temp = h >>> 16; /** * 进行按位异或(XOR)运算,按位异或就是把两个数按二进制,相同就取0,不同就取1。 * 比如:0101 ^ 1110 的结果为 1011 * 任何一个数,与0按位异或的结果都是这个数本身: * 0 ^ 0 = 0, 1 ^ 0 = 1 * 所以这里的含义是保留高16位,而低16位则会因XOR运算得出不同的数值 * 这样做的好处是: * 自己的高半区和低半区做异或,就是为了混合原始哈希码的高位和低位,以此来加大低位的随机性 * 从而降低哈希冲突 * */ int newHash = h ^ temp; return newHash; } /** * 这里正好解释了数组长度为什么一定要是2的整次幂 * 因为这样数组长度-1刚好能成为一个低位掩码 * 任何数与数组长度-1做与运算,相当于做取模(%)运算,不过会比%运算效率高 * 例如数组长度为16,那么18和16的模相当于18 & (16-1) * 0001 0010 & 0000 1111 = 0000 0010 = 十进制的2 */ static final int indexFor(int hash, int tableLength){ return hash & (tableLength - 1); } //扩容为原来的两倍 final void doubleSize(){ int newCapacity = table.length << 1; Entry<K, V>[] newTable = new Entry[newCapacity]; threshold = (int)(newCapacity * loadFactor); //需要再散列 hashAgain(newTable); table = newTable; } //再散列 final void hashAgain(Entry<K, V>[] newTable){ Entry<K, V>[] source = table; int newCapacity = newTable.length; for (int i=0; i<source.length; i++){ Entry<K, V> e = source[i]; if (null != e){ source[i] = null; do { Entry<K, V> next = e.next; int index = indexFor(e.hash, newCapacity); e.next = newTable[index]; newTable[index] = e; e = next; } while (null != e); } } } @Override public V get(K key) { int index = indexFor(hash(key), table.length); int hash = hash(key); Entry<K, V> e = table[index]; while (null != e){ if (hash == e.hash && (e.key == key || key.equals(e.key)) ) return e.value; e = e.next; } return null; } @Override public int size() { return size; } private static class Entry<K, V> implements IMyMap.Entry{ Entry<K, V> next; V value; final K key; final int hash; public Entry(Entry<K, V> next, V value, K key, int hash) { this.next = next; this.value = value; this.key = key; this.hash = hash; } }}
阅读全文
0 0
- 【java集合】自己实现简易的HashMap~改良
- 【java集合】自己实现简易的HashMap
- 【java集合】自己实现简易的HashSet
- 【java集合】自己实现简易的Hashtable
- 【java集合】自己实现简易的ArrayList
- 【java集合】自己实现简易的LinkedList
- 自己实现简易HashMap
- java自己实现的简单的hashMap
- Java集合----HashMap的实现原理
- Core Java --集合--HashMap的实现原理
- Java集合1:HashMap的实现原理
- 深入Java集合:HashMap的实现原理
- Java集合中HashMap的实现原理
- 实现自己的HashMap
- 实现自己的HashMap
- 自己实现的hashmap
- 根据数组+链表的原理,自己实现一个简易版的HashMap
- 进程集合的简易实现
- bzoj 4827 [Hnoi2017]礼物(FFT)
- 计算机图形学
- FZU 2214 Knapsack problem (超大容量背包)
- 6、Oracle单行函数
- 需求(Java);利用Jsoup架包获取指定网页的全部图片,并自动下载到指定文件夹中
- 【java集合】自己实现简易的HashMap~改良
- 今日内容介绍 1、自定义类型的定义及使用 2、自定义类的内存图 3、ArrayList集合的基本功能 4、随机点名器案例及库存案例代码优化 ###01引用数据类型_类 * A: 数据类型
- day07笔记
- Spring 整合 Quartz 实现动态定时任务
- LVS负载均衡服务的工作原理及方式
- 基于事件通知的重叠I/O网络模型
- matlab如何写一个类
- 编译caffe出现错误 opencv
- bzoj 4810 [Ynoi2017]由乃的玉米田(莫队+bitset)