内部节点类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Node<K,V> { private K key; private V value; private Node<K,V> next; public Node(K key, V value) { this.key = key; this.value = value; } public Node(K key, V value, Node<K,V> next) { this.key = key; this.value = value; this.next = next; } }
|
成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
final int MAXIMUM_CAPACITY = 1 << 30;
final float DEFAULT_LOAD_FACTOR = 0.75f;
final int TREEIFY_THRESHOLD = 8;
final int UNTREEIFY_THRESHOLD = 6;
final int MIN_TREEIFY_CAPACITY = 64;
transient Node<K,V>[] table;
transient int size;
transient int modCount;
|
构造方法
1 2 3 4 5 6 7 8 9 10
| public ThirdHashMap() { buckets = new Node[DEFAULT_CAPACITY]; size = 0; }
public ThirdHashMap(int capacity) { buckets = new Node[capacity]; size = 0; }
|
散列函数
1 2 3 4 5 6 7
| private int getIndex(K key, int length) { int hashCode = key.hashCode(); int index = hashCode % length; return Math.abs(index); }
|
put方法
基本逻辑:
- 获取元素插入位置
- 当前位置为空,直接插入
- 位置不为空,发生冲突,遍历链表
- 如果元素key和节点相同,覆盖,否则新建节点插入链表头部
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public void put(K key, V value) { if(size >= buckets.length * LOAD_FACTOR) resize(); putVal(key, value, buckets); } private void putVal(K key, V value, Node<K, V>[] table) { int index = getIndex(key, table.length); Node node = table[index]; if(node == null) { table[index] = new Node<>(key, value); size++; return; } while(node != null) { if((node.key.hashCode() == key.hashCode()) && (node.key == key || node.key.equals(key))) { node.value = value; return; } node = node.next; } Node newNode = new Node(key, value, table[index]); table[index] = newNode; size++; }
|
get方法
通过散列函数获取地址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public V get(K key) { int index = getIndex(key, buckets.length); if(buckets[index] == null) return null; Node<K,V> node = buckets[index]; while(node != null) { if((node.key.hashCode() == key.hashCode()) && (node.key == key || node.key.equals(key))) { return node.value; } node = node.next; } return null; }
|
扩容方法
- 创建两倍容量的新数组
- 将当前桶数组的元素重新散列到新的数组
- 新数组置为map的桶数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| private void resize() { Node<K,V>[] newBuckets = new Node[buckets.length * 2]; rehash(newBuckets); buckets = newBuckets; }
private void rehash(Node<K,V>[] newBuckets) { size = 0; for(int i = 0;i<buckets.length;i++) { if(buckets[i] == null) { continue; } Node<K,V> node = buckets[i]; while(node != null) { putVal(node.key, node.value, newBuckets); node = node.next; } } }
|
参考
[1] 牛客网,手写HashMap。https://www.nowcoder.com/discuss/997806
[2] jdk1.8 HashMap源码