1.HashMap的一些重要成员属性
1.1) 默认的初始容量 DEFAULT_INITIAL_CAPACITY = 1 << 4,官方建议必须时2的次方数
1.2) 负载因子DEFAULT_LOAD_FACTOR = 0.75f; 用来HashMap扩容判断
1.3) Node<K,V>[] table; ---容器中的元素
2.HashMap的构造方法
1.1) 无参构造函数
1.2) 带容量的有参构造函数
1.3) 带容量和负载因子的有参构造函数
3.HashMap的hash方法
3.1) step1: 获取到 key的hashcode值
3.2) step2: 将step1计算得到的值无符号右移16位
3.3) step3: 将 step1 和 step2 的结果异或运算得到结果
4.HashMap容器中的重要元素类Node的组成
4.1) hash值
4.2) key 和 value值
4.3) hash值相同时,变成链表结果的下一个Node
static class Node<K,V>{
final int hash;
final K key;
V value;
Node<K,V> next;
public Node(int hash, K key, V value, Node<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
@Override
public String toString() {
return key + " = " + value;
}
//设置成新值,返回旧值
public final V setValue(V newValue) {
V oldValue = value;
this.value = newValue;
return oldValue;
}
@Override
public int hashCode() {
return Objects.hash(key) ^ Objects.hash(value);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?, ?> node = (Node<?, ?>) o;
return Objects.equals(key, node.key) &&
Objects.equals(value, node.value);
}
}
5.HashMap的put方法
5.1) 计算出HashMap中数组所在的下标值---步骤3的hash值 和 HashMap容量的值减去1做与运算
从上面的表格可以看出容量的大小,必须为2的次方数,不然最终数组会有下标遗漏
5.2) HashMap容器put方法的返回值是旧值
5.3) HashMap扩容时,在进行元素的重新分配时,针对单向链表需要明确以下节点
5.3.1) 在同一个链表中,则说明这个链表中所有元素的hash值是相同的
5.3.2) HashMap扩容标准是2的次方数,从4->8->16....
5.3.3) 从5.1)可以得知hash值二进制在旧的容量所在二进制所处的位置是0 还是1 ,即可计算出当前整个链表
在新的HashMap容器中所处的位置
public V put(K key, V value) {
return putVal(hash(key), key, value);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
private V putVal(int hash, K key, V value) {
//定义一个临时变量用来存储HashMap容器的容量大小
int capacity;
//定义一个新元素在HashMap中数组里面的下表位置
int currentIndex;
//把HashMap容器的元素赋值给一个临时变量
Node<K, V>[] tempTable = table;
//如果HashMap容器为空或者容量为0,则需要扩容
if (tempTable == null || tempTable.length == 0) {
tempTable = resize();
}
capacity = tempTable.length;
//计算新增的值将要存储的位置
currentIndex = (capacity - 1) & hash;
//从HashMap中取出当前位置的元素
Node<K, V> tempNode = tempTable[currentIndex];
//如果HashMap容器的当前位置还没有存储元素
//则直接把信元素赋值到这个位置即可
if (tempNode == null) {
tempTable[currentIndex] = new Node<>(hash, key, value, null);
} else {
Node<K, V> modifyNode = null;
//如果当前位置已经存储了元素,则需要根据不同的情况来处理这个元素
Node<K, V> currentNode = tempNode;
//1.如果新增的元素的hash(key)相同,并且(key 的对象 和 当前对象 相等 || key!=null && key值和当前的key相等),
// 则需要更新当前节点的值
//2.如果当前节点的类型是红黑树,则进入红黑树的逻辑进行处理--这里不做说明
//3.进入单线链表的循环处理,如果在链表中找到和新增的元素的hash(key),key值和当前节点的都相同,并且key!= null的节点
//只需把这个节点的值更新即可,否则直接添加到链表的末尾
K currentKey = currentNode.key;
int currentHash = currentNode.hash;
if (currentHash == hash && (currentKey == key || key != null && key.equals(currentKey))) {
modifyNode = currentNode;
} else if (currentNode instanceof TreeNode) {
//TODO jdk1.8后才有的
} else {
for (int bitCount = 0; ; bitCount++) {
Node<K, V> nextNode = currentNode.next;
//如果当前节点的下一个节点为null,则到了单向链表的尾节点
//直接把新元素添加到单向链表的结尾即可
if (nextNode == null) {
nextNode.next = new Node<>(hash, key, value, null);
if (bitCount >= TREEIFY_THRESHOLD - 1) {
//TODO 如果单向链表的元素个数大于所设置的向红黑树转变的条件,则需要处理
}
break;
}
//如果当前节点的下一个节点不为null,则判断新节点和当前节点是否满足相同节点的条件
if (nextNode.hash == hash && (nextNode.key == key || key != null && key.equals(nextNode.key))) {
modifyNode = nextNode;
break;
}
//如果没有遍历到单向链表的末尾,并且新节点不是当前节点
//则继续遍历
currentNode = nextNode;
}
}
//如果在单向链表中存在节点和新节点相同的条件,则只需要把旧节点的数据修改成新的值即可
if (modifyNode != null) {
V oldValue = modifyNode.value;
//TODO 如果有参数设置,节点已经存在,切节点的值不为null就不在添加,则不需要更新节点的值
modifyNode.value = value;
return oldValue;
}
}
size++;
//如果容器中元素的个数大于
// HashMap容器根据负载因子设置的阈值
// 则需要扩容,并重新分配HashMap中元素的位置
if (size > threshold) {
resize();
}
return null;
}
/**
* 初始化HashMap容器,或者重新分配HashMap容器中元素的位置
* 因为当HashMap容器中元素超过一定的数量,需要扩容,
* 而扩容之后元素hash值发生变化,所以需要重新分配HashMap容器中元素的位置
*/
final Node<K, V>[] resize() {
//定义一个临时变量存储旧的HashMap容器中的元素集合
Node<K, V>[] oldTable = table;
//旧HashMap容器的容量大小为
int oldCapacity = oldTable == null ? 0 : oldTable.length;
//旧的扩容标准
int oldThreshold = threshold;
//定义临时变量存储新容器容量和新扩容标准
int newCapactity = 0;
int newThreshold = 0;
//如果旧的HashMap容器大于0
if (oldCapacity > 0) {
//如果旧的HashMap容器已经达到HashMap允许的最大容量
//则只需把扩容标准放大到最大即可
if (oldCapacity >= MAXIMUM_CAPACITY) {
threshold = MAXIMUM_CAPACITY;
return oldTable;
}
//如果旧的HashMap容器还没有达到HashMap允许的最大容量
//则把旧的容量扩大两倍作为新的容器的容量
newCapactity = oldCapacity << 1;
//如果扩大后的容器容量小于HashMap允许的最大容量
//并且大于等于默认的最小初始容量
//则把旧的扩容标准加倍
if (newCapactity < MAXIMUM_CAPACITY && newCapactity >= DEFAULT_INITIAL_CAPACITY) {
newThreshold = oldThreshold << 1;
}
}
//如果旧的扩容标准大于0
else if (oldThreshold > 0) {
newCapactity = oldThreshold;
} else {
// 如果上面两个条件都不满足,则取HashMap容器默认的标准
newCapactity = DEFAULT_INITIAL_CAPACITY;
newThreshold = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
threshold = newThreshold;
//使用新的容量创建HashMap容器
Node<K, V>[] newTable = (Node<K, V>[]) new Node[newCapactity];
//将新HashMap容器赋值给HashMap容器
table = newTable;
//如果旧的HashMap容器不为空,则需要重新分配HashMap容器中的元素
if (oldTable != null) {
for (int i = 0; i < oldCapacity; i++) {
Node<K, V> currentNode = oldTable[i];
//旧HashMap容器当前位置不为空,则需要根据新的容量重新计算该元素应该存放的位置
if (currentNode != null) {
oldTable[i] = null;//为了让GC回收
//判断当前节点是否有下下一个节点,如果没有,则直接进行元素位置的重新计算
if (currentNode.next == null) {
int currentHash = currentNode.hash;
int newIndex = currentHash & (newCapactity - 1);
newTable[newIndex] = currentNode;
} else if (currentNode instanceof TreeNode) {
//TODO 如果当前节点的类型是红黑树
} else {
//同一个单向链表中元素的hash值是相等的
//因此在新的HashMap容器中,这个链表中所有的元素,
// 也还是在相同的位置,并且是链表的格式存储
Node<K, V> highHeadNode = null;
Node<K, V> highTailNode = null;
Node<K, V> lowHeadNode = null;
Node<K, V> lowTailNode = null;
do {
int currentHash = currentNode.hash;
int hashLocation = currentHash & oldCapacity;
if (hashLocation == 0){
//如果尾部节点还没有设置,则说明此时还没有头结点
if(lowTailNode == null){
lowHeadNode = currentNode;
}else{
lowTailNode.next = currentNode;
}
lowTailNode = currentNode;
}else{
if(highTailNode == null){
highHeadNode = currentNode;
}else{
highTailNode.next = currentNode;
}
highTailNode = currentNode;
}
//继续循环当前节点的下一个节点
currentNode = currentNode.next;
} while (currentNode.next != null);
//如果hash&oldCapacity = 0 则说明这个链表的元素在新HashMap容器中,数组下表位置不变
if(lowTailNode != null){
lowTailNode.next = null;
newTable[i] = lowHeadNode;
}
if(highTailNode != null){
highTailNode.next = null;
newTable[i + oldCapacity] = highHeadNode;
}
}
}
}
}
return newTable;
}
6.HashMap的get方法
public V get(Object key) {
Node<K, V> node = null;
node = getNode(hash(key), key);
return node == null ? null : node.value;
}
private Node<K, V> getNode(int hash, Object key) {
Node<K, V>[] tempTable = table;
int capacity = tempTable.length;
//如果当前HashMap容器为空或者其容量为0,则直接返回null
if (tempTable == null || capacity == 0) {
return null;
}
//要查找的key值,如果存在,则在容器中的位置为
int location = hash & (capacity - 1);
Node<K, V> firstNode = tempTable[location];
if (firstNode == null) {
return null;
}
if (firstNode.hash == hash
&& (firstNode.key == key
|| (key != null && key.equals(firstNode.key)))) {
return firstNode;
}
Node<K,V> nextNode = firstNode.next;
//是不是链表
if(nextNode != null){
if(nextNode instanceof TreeNode){
//TODO 红黑树结构的处理
}else{
do{
if (nextNode.hash == hash
&& (nextNode.key == key
|| (key != null && key.equals(nextNode.key)))) {
return nextNode;
}
nextNode = nextNode.next;
}while (nextNode != null);
}
}
return null;
}
7.HashMap的remove方法
public V remove(Object key) {
Node<K, V> removeNode = null;
removeNode = removeNode(hash(key), key);
return removeNode == null ? null : removeNode.value;
}
private Node<K, V> removeNode(int hash, Object key) {
Node<K, V> removeNode = null;
Node<K, V> prevNode = null;
Node<K, V>[] tempTable = table;
int capacity = tempTable.length;
//如果当前HashMap容器为空或者其容量为0,则直接返回null
if (tempTable == null || capacity == 0) {
return null;
}
//要查找的key值,如果存在,则在容器中的位置为
int location = hash & (capacity - 1);
Node<K, V> firstNode = tempTable[location];
if (firstNode == null) {
return null;
}
if (firstNode.hash == hash
&& (firstNode.key == key
|| (key != null && key.equals(firstNode.key)))) {
removeNode = firstNode;
prevNode = firstNode;
}
Node<K, V> nextNode = firstNode.next;
//是不是链表
if (removeNode == null & nextNode != null) {
if (nextNode instanceof TreeNode) {
//TODO 红黑树结构的处理
} else {
do {
if (nextNode.hash == hash
&& (nextNode.key == key
|| (key != null && key.equals(nextNode.key)))) {
removeNode = nextNode;
break;
}
prevNode = nextNode;
nextNode = nextNode.next;
} while (nextNode != null);
}
}
//如果要删除的元素存在
if (removeNode != null) {
//如果删除的是
if (removeNode instanceof TreeNode) {
//TODO 红黑树
}
//如果删除不是单向链表,这个位置只有一个元素,并且匹配上了
else if (removeNode == prevNode) {
tempTable[location] = removeNode.next;
}else{
prevNode.next = removeNode.next;
}
--size;
return removeNode;
}
return null;
}
8.自己手写HashMap源码代码以及Junit测试类
package com.roger.collection.impl;
import javax.swing.tree.TreeNode;
import java.util.Objects;
public class RogerHashMap<K, V> {
//单向链表转向红黑树的条件判断
static final int TREEIFY_THRESHOLD = 8;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//HashMap中数组的最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;
static final float DEFAULT_LOAD_FACTOR = 0.75F;
static class Node<K, V> {
final int hash;
final K key;
V value;
Node<K, V> next;
public Node(int hash, K key, V value, Node<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
@Override
public String toString() {
return key + " = " + value;
}
//设置成新值,返回旧值
public final V setValue(V newValue) {
V oldValue = value;
this.value = newValue;
return oldValue;
}
@Override
public int hashCode() {
return Objects.hash(key) ^ Objects.hash(value);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?, ?> node = (Node<?, ?>) o;
return Objects.equals(key, node.key) &&
Objects.equals(value, node.value);
}
}
//HashMap容器下一次扩容的标准
//即当HashMap容器中元素的个数大于这个值
//就会触发HashMap容器扩容
//JDK1.8保证这个值是2的次方数
int threshold;
//负载因子
final float loadFactor;
//HashMap容器中元素的个数
int size;
public RogerHashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
public RogerHashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
public RogerHashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("Illegal initial capacity : " + initialCapacity);
}
if (initialCapacity > MAXIMUM_CAPACITY) {
initialCapacity = MAXIMUM_CAPACITY;
}
if (loadFactor < 0) {
throw new IllegalArgumentException("Illegal load factor : " + loadFactor);
}
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
Node<K, V>[] table;
public V get(Object key) {
Node<K, V> node = null;
node = getNode(hash(key), key);
return node == null ? null : node.value;
}
private Node<K, V> getNode(int hash, Object key) {
Node<K, V>[] tempTable = table;
int capacity = tempTable.length;
//如果当前HashMap容器为空或者其容量为0,则直接返回null
if (tempTable == null || capacity == 0) {
return null;
}
//要查找的key值,如果存在,则在容器中的位置为
int location = hash & (capacity - 1);
Node<K, V> firstNode = tempTable[location];
if (firstNode == null) {
return null;
}
if (firstNode.hash == hash
&& (firstNode.key == key
|| (key != null && key.equals(firstNode.key)))) {
return firstNode;
}
Node<K, V> nextNode = firstNode.next;
//是不是链表
if (nextNode != null) {
if (nextNode instanceof TreeNode) {
//TODO 红黑树结构的处理
} else {
do {
if (nextNode.hash == hash
&& (nextNode.key == key
|| (key != null && key.equals(nextNode.key)))) {
return nextNode;
}
nextNode = nextNode.next;
} while (nextNode != null);
}
}
return null;
}
public V remove(Object key) {
Node<K, V> removeNode = null;
removeNode = removeNode(hash(key), key);
return removeNode == null ? null : removeNode.value;
}
private Node<K, V> removeNode(int hash, Object key) {
Node<K, V> removeNode = null;
Node<K, V> prevNode = null;
Node<K, V>[] tempTable = table;
int capacity = tempTable.length;
//如果当前HashMap容器为空或者其容量为0,则直接返回null
if (tempTable == null || capacity == 0) {
return null;
}
//要查找的key值,如果存在,则在容器中的位置为
int location = hash & (capacity - 1);
Node<K, V> firstNode = tempTable[location];
if (firstNode == null) {
return null;
}
if (firstNode.hash == hash
&& (firstNode.key == key
|| (key != null && key.equals(firstNode.key)))) {
removeNode = firstNode;
prevNode = firstNode;
}
Node<K, V> nextNode = firstNode.next;
//是不是链表
if (removeNode == null & nextNode != null) {
if (nextNode instanceof TreeNode) {
//TODO 红黑树结构的处理
} else {
do {
if (nextNode.hash == hash
&& (nextNode.key == key
|| (key != null && key.equals(nextNode.key)))) {
removeNode = nextNode;
break;
}
prevNode = nextNode;
nextNode = nextNode.next;
} while (nextNode != null);
}
}
//如果要删除的元素存在
if (removeNode != null) {
//如果删除的是
if (removeNode instanceof TreeNode) {
//TODO 红黑树
}
//如果删除不是单向链表,这个位置只有一个元素,并且匹配上了
else if (removeNode == prevNode) {
tempTable[location] = removeNode.next;
}else{
prevNode.next = removeNode.next;
}
--size;
return removeNode;
}
return null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
private V putVal(int hash, K key, V value) {
//定义一个临时变量用来存储HashMap容器的容量大小
int capacity;
//定义一个新元素在HashMap中数组里面的下表位置
int currentIndex;
//把HashMap容器的元素赋值给一个临时变量
Node<K, V>[] tempTable = table;
//如果HashMap容器为空或者容量为0,则需要扩容
if (tempTable == null || tempTable.length == 0) {
tempTable = resize();
}
capacity = tempTable.length;
//计算新增的值将要存储的位置
currentIndex = (capacity - 1) & hash;
//从HashMap中取出当前位置的元素
Node<K, V> tempNode = tempTable[currentIndex];
//如果HashMap容器的当前位置还没有存储元素
//则直接把信元素赋值到这个位置即可
if (tempNode == null) {
tempTable[currentIndex] = new Node<>(hash, key, value, null);
} else {
Node<K, V> modifyNode = null;
//如果当前位置已经存储了元素,则需要根据不同的情况来处理这个元素
Node<K, V> currentNode = tempNode;
//1.如果新增的元素的hash(key)相同,并且(key 的对象 和 当前对象 相等 || key!=null && key值和当前的key相等),
// 则需要更新当前节点的值
//2.如果当前节点的类型是红黑树,则进入红黑树的逻辑进行处理--这里不做说明
//3.进入单线链表的循环处理,如果在链表中找到和新增的元素的hash(key),key值和当前节点的都相同,并且key!= null的节点
//只需把这个节点的值更新即可,否则直接添加到链表的末尾
K currentKey = currentNode.key;
int currentHash = currentNode.hash;
if (currentHash == hash && (currentKey == key || key != null && key.equals(currentKey))) {
modifyNode = currentNode;
} else if (currentNode instanceof TreeNode) {
//TODO jdk1.8后才有的
} else {
for (int bitCount = 0; ; bitCount++) {
Node<K, V> nextNode = currentNode.next;
//如果当前节点的下一个节点为null,则到了单向链表的尾节点
//直接把新元素添加到单向链表的结尾即可
if (nextNode == null) {
nextNode.next = new Node<>(hash, key, value, null);
if (bitCount >= TREEIFY_THRESHOLD - 1) {
//TODO 如果单向链表的元素个数大于所设置的向红黑树转变的条件,则需要处理
}
break;
}
//如果当前节点的下一个节点不为null,则判断新节点和当前节点是否满足相同节点的条件
if (nextNode.hash == hash && (nextNode.key == key || key != null && key.equals(nextNode.key))) {
modifyNode = nextNode;
break;
}
//如果没有遍历到单向链表的末尾,并且新节点不是当前节点
//则继续遍历
currentNode = nextNode;
}
}
//如果在单向链表中存在节点和新节点相同的条件,则只需要把旧节点的数据修改成新的值即可
if (modifyNode != null) {
V oldValue = modifyNode.value;
//TODO 如果有参数设置,节点已经存在,切节点的值不为null就不在添加,则不需要更新节点的值
modifyNode.value = value;
return oldValue;
}
}
size++;
//如果容器中元素的个数大于
// HashMap容器根据负载因子设置的阈值
// 则需要扩容,并重新分配HashMap中元素的位置
if (size > threshold) {
resize();
}
return null;
}
/**
* 初始化HashMap容器,或者重新分配HashMap容器中元素的位置
* 因为当HashMap容器中元素超过一定的数量,需要扩容,
* 而扩容之后元素hash值发生变化,所以需要重新分配HashMap容器中元素的位置
*/
final Node<K, V>[] resize() {
//定义一个临时变量存储旧的HashMap容器中的元素集合
Node<K, V>[] oldTable = table;
//旧HashMap容器的容量大小为
int oldCapacity = oldTable == null ? 0 : oldTable.length;
//旧的扩容标准
int oldThreshold = threshold;
//定义临时变量存储新容器容量和新扩容标准
int newCapactity = 0;
int newThreshold = 0;
//如果旧的HashMap容器大于0
if (oldCapacity > 0) {
//如果旧的HashMap容器已经达到HashMap允许的最大容量
//则只需把扩容标准放大到最大即可
if (oldCapacity >= MAXIMUM_CAPACITY) {
threshold = MAXIMUM_CAPACITY;
return oldTable;
}
//如果旧的HashMap容器还没有达到HashMap允许的最大容量
//则把旧的容量扩大两倍作为新的容器的容量
newCapactity = oldCapacity << 1;
//如果扩大后的容器容量小于HashMap允许的最大容量
//并且大于等于默认的最小初始容量
//则把旧的扩容标准加倍
if (newCapactity < MAXIMUM_CAPACITY && newCapactity >= DEFAULT_INITIAL_CAPACITY) {
newThreshold = oldThreshold << 1;
}
}
//如果旧的扩容标准大于0
else if (oldThreshold > 0) {
newCapactity = oldThreshold;
} else {
// 如果上面两个条件都不满足,则取HashMap容器默认的标准
newCapactity = DEFAULT_INITIAL_CAPACITY;
newThreshold = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
threshold = newThreshold;
//使用新的容量创建HashMap容器
Node<K, V>[] newTable = (Node<K, V>[]) new Node[newCapactity];
//将新HashMap容器赋值给HashMap容器
table = newTable;
//如果旧的HashMap容器不为空,则需要重新分配HashMap容器中的元素
if (oldTable != null) {
for (int i = 0; i < oldCapacity; i++) {
Node<K, V> currentNode = oldTable[i];
//旧HashMap容器当前位置不为空,则需要根据新的容量重新计算该元素应该存放的位置
if (currentNode != null) {
oldTable[i] = null;//为了让GC回收
//判断当前节点是否有下下一个节点,如果没有,则直接进行元素位置的重新计算
if (currentNode.next == null) {
int currentHash = currentNode.hash;
int newIndex = currentHash & (newCapactity - 1);
newTable[newIndex] = currentNode;
} else if (currentNode instanceof TreeNode) {
//TODO 如果当前节点的类型是红黑树
} else {
//同一个单向链表中元素的hash值是相等的
//因此在新的HashMap容器中,这个链表中所有的元素,
// 也还是在相同的位置,并且是链表的格式存储
Node<K, V> highHeadNode = null;
Node<K, V> highTailNode = null;
Node<K, V> lowHeadNode = null;
Node<K, V> lowTailNode = null;
do {
int currentHash = currentNode.hash;
int hashLocation = currentHash & oldCapacity;
if (hashLocation == 0) {
//如果尾部节点还没有设置,则说明此时还没有头结点
if (lowTailNode == null) {
lowHeadNode = currentNode;
} else {
lowTailNode.next = currentNode;
}
lowTailNode = currentNode;
} else {
if (highTailNode == null) {
highHeadNode = currentNode;
} else {
highTailNode.next = currentNode;
}
highTailNode = currentNode;
}
//继续循环当前节点的下一个节点
currentNode = currentNode.next;
} while (currentNode.next != null);
//如果hash&oldCapacity = 0 则说明这个链表的元素在新HashMap容器中,数组下表位置不变
if (lowTailNode != null) {
lowTailNode.next = null;
newTable[i] = lowHeadNode;
}
if (highTailNode != null) {
highTailNode.next = null;
newTable[i + oldCapacity] = highHeadNode;
}
}
}
}
}
return newTable;
}
}
package com.roger.collection.impl;
import org.junit.Test;
import static org.junit.Assert.*;
public class RogerHashMapTest {
@Test
public void testPut() {
RogerHashMap<String, Object> rogerHashMap = new RogerHashMap<>(2);
rogerHashMap.put("name", "Roger");
rogerHashMap.put("age", 12);
rogerHashMap.put("address", "上海");
rogerHashMap.remove("name");
System.out.println("name:" + rogerHashMap.get("name"));
System.out.println("age:" + rogerHashMap.get("age"));
System.out.println("address:" + rogerHashMap.get("address"));
}
}