java中Hashmap的实现原理
来源:互联网 发布:网红淘宝店质量 编辑:程序博客网 时间:2024/04/20 04:37
一、解HashMap源码解读
1、HashMap的存储结构
2、HashMap的初始化
3、元素Hash值获取及通过hash值找到talbe下标索引
4、元素添加方法addEntry
5、HashMap扩容
6、老table重新hash成新table
7、key为null,存到哪去了
8、查找元素get(Object key)
9、根据key删除元素
1、HashMap的存储结构
在HashMap的Field中有:
- transient Entry[] table;
而Entry的定义如下:
- static class Entry<K,V> implements Map.Entry<K,V> {
- final K key;
- V value;
- Entry<K,V> next;
- final int hash;
- .........
- }
简单说就是一个数组+链表,结构如下图:
2、HashMap的初始化
- public HashMap() {
- this.loadFactor = DEFAULT_LOAD_FACTOR;
- threshold=(int)(DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR);
- table = new Entry[DEFAULT_INITIAL_CAPACITY];
- init();
- }
- public HashMap() {
- this.loadFactor = DEFAULT_LOAD_FACTOR;
- threshold=(int)(DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR);
- table = new Entry[DEFAULT_INITIAL_CAPACITY];
- init();
- }
- static int hash(int h) {
- h ^= (h >>> 20) ^ (h >>> 12);
- return h ^ (h >>> 7) ^ (h >>> 4);
- }
- static int indexFor(int h, int length) {
- return h & (length-1);
- }
这个就是获得元素对应table下标索引的方法,h是通过上面的hash(int h)方法获得,length是table的长度
4、元素添加方法addEntry
- void addEntry(int hash, K key, V value, int bucketIndex) {
- Entry<K,V> e = table[bucketIndex];
- table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
- if (size++ >= threshold)
- resize(2 * table.length);
- }
- //Entry的构造方法
- Entry(int h, K k, V v, Entry<K,V> n) {
- value = v;
- next = n;
- key = k;
- hash = h;
- }
- void resize(int newCapacity) {
- Entry[] oldTable = table;
- int oldCapacity = oldTable.length;
- if (oldCapacity == MAXIMUM_CAPACITY) {
- threshold = Integer.MAX_VALUE;
- return;
- }
- Entry[] newTable = new Entry[newCapacity];
- transfer(newTable);
- table = newTable;
- threshold = (int)(newCapacity * loadFactor);
- }
- if (size++ >= threshold)
- resize(2 * table.length);
- void transfer(Entry[] newTable) {
- Entry[] src = table;
- int newCapacity = newTable.length;
- for (int j = 0; j < src.length; j++) {
- Entry<K,V> e = src[j];
- if (e != null) {
- src[j] = null;
- do {
- Entry<K,V> next = e.next;
- int i = indexFor(e.hash, newCapacity);
- e.next = newTable[i];
- newTable[i] = e;
- e = next;
- } while (e != null);
- }
- }
- }
- if (key == null)
- return putForNullKey(value);
- //那就看看这个putForNullKey是怎么处理的吧。
- private V putForNullKey(V value) {
- for (Entry<K,V> e = table[0]; e != null; e = e.next) {
- if (e.key == null) {
- V oldValue = e.value;
- e.value = value;
- e.recordAccess(this);
- return oldValue;
- }
- }
- modCount++;
- addEntry(0, null, value, 0);
- return null;
- }
- public V get(Object key) {
- if (key == null)
- return getForNullKey();
- int hash = hash(key.hashCode());
- for (Entry<K,V> e = table[indexFor(hash, table.length)];e != null;e = e.next) {
- Object k;
- if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
- return e.value;
- }
- return null;
- }
- public V remove(Object key) {
- Entry<K,V> e = removeEntryForKey(key);
- return (e == null ? null : e.value);
- }
- 调用的还是下面的方法
- final Entry<K,V> removeEntryForKey(Object key) {
- int hash = (key == null) ? 0 : hash(key.hashCode());
- int i = indexFor(hash, table.length);
- Entry<K,V> prev = table[i];
- Entry<K,V> e = prev;
- while (e != null) {
- Entry<K,V> next = e.next;
- Object k;
- if (e.hash == hash &&
- ((k = e.key) == key || (key != null && key.equals(k)))) {
- modCount++;
- size--;
- if (prev == e)
- table[i] = next;
- else
- prev.next = next;
- e.recordRemoval(this);
- return e;
- }
- prev = e;
- e = next;
- }
- return e;
- }
二.解决hash冲突的办法
- 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法
- 链地址法
- 建立一个公共溢出区
Java中hashmap的解决办法就是采用的链地址法。
三.实现自己的HashMap
Entry.java
MyHashMap.java
MyHashMapTest.java
- package edu.sjtu.erplab.hash;
- public class MyHashMapTest {
- public static void main(String[] args) {
- MyHashMap<Integer, Integer> map = new MyHashMap<Integer, Integer>();
- map.put(1, 90);
- map.put(2, 95);
- map.put(17, 85);
- System.out.println(map.get(1));
- System.out.println(map.get(2));
- System.out.println(map.get(17));
- System.out.println(map.get(null));
- }
- }
0 0
- Java中HashMap的实现原理
- java中Hashmap的实现原理
- java中Hashmap的实现原理
- java中Hashmap的实现原理
- Java中HashMap的实现原理
- Java集合中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理分析
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- Java中HashMap的实现原理
- java中HashMap实现原理
- Java的HashMap实现原理
- java HashMap的实现原理
- Java中的浮点型(Double&Float)计算问题
- 手势使用
- spring整合mybatis,dao层类注入不进去
- 安装配置Oracle Instance Client
- mvn archetype:create报错
- java中Hashmap的实现原理
- cocos2d-x 3.0 android mk文件 之 自动遍历*.cpp文件
- 欧几里得(Eculid)最大公约数(GCD)算法
- 8x25 平台上添加虚拟按键
- 麻烦死了
- POJ 1555
- 可我仍然为自己违背了父亲多年的教诲而感到内疚自责
- C++的函数重载
- 【在数字键盘上添加button】