HashMap是Java中最常用的数据结构之一,它提供了高效的插入、查找和删除操作。本篇博客将深入解析HashMap的常见操作,包括元素的插入、查找、删除以及遍历等。
关于HashMap内部实现原理的内容如下
HashMap详解-内部实现原理(1)-数组和桶
HashMap详解-内部实现原理(2)-哈希函数
HashMap详解-内部实现原理(3)-扩容机制
在浏览本章前可以了解一下以上知识,或许会给你提供一些帮助
static int compareComparables(Class<?> kc, Object k, Object x) {
return (x == null || x.getClass() != kc ? 0 :
((Comparable)k).compareTo(x));
}
方法签名:static int compareComparables(Class> kc, Object k, Object x)
函数逻辑:
compareTo()
方法来比较k和x的大小。注意事项:
该方法假设k实现了Comparable接口,并且x的类型与kc相同或是其子类。
如果x为null或其类型与kc不一致,表示无法进行比较,返回0。
这段代码通常在排序算法或需要比较对象大小的场景中使用。通过调用compareTo()
方法,可以实现不同类型对象的比较操作。请注意在使用时要确保对象类型的一致性,以避免可能的ClassCastException
异常。
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
这段代码是Java中HashMap类的构造函数,用于初始化HashMap对象。
构造函数签名:public HashMap(int initialCapacity, float loadFactor)
构造函数逻辑:
initialCapacity
是否小于0,如果是则抛出IllegalArgumentException
异常,提示初始容量为非法值。initialCapacity
是否大于MAXIMUM_CAPACITY
(HashMap中定义的最大容量),如果是,则将初始容量设置为MAXIMUM_CAPACITY
。loadFactor
是否小于等于0或者为NaN(不是一个数字),如果是,则抛出IllegalArgumentException
异常,提示负载因子为非法值。this.loadFactor
。this.threshold
。注意事项:
这段代码在创建HashMap对象时会被调用,用于初始化HashMap的各项参数,并计算出合适的容量大小。
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
这段代码是HashMap类中的一个私有方法,用于向哈希表中插入键值对。具体解释如下:
方法签名:final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict)
方法逻辑:
注意事项:
final Node<K,V> getNode(Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n, hash; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & (hash = hash(key))]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
这段代码是HashMap类中的一个私有方法,用于根据给定的 key 查找并返回对应的节点。
方法签名:final Node
方法逻辑:
注意事项:
final Node<K,V> removeNode(int hash, Object key, Object value,
boolean matchValue, boolean movable) {
Node<K,V>[] tab; Node<K,V> p; int n, index;
if ((tab = table) != null && (n = tab.length) > 0 &&
(p = tab[index = (n - 1) & hash]) != null) {
Node<K,V> node = null, e; K k; V v;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
node = p;
else if ((e = p.next) != null) {
if (p instanceof TreeNode)
node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
else {
do {
if (e.hash == hash &&
((k = e.key) == key ||
(key != null && key.equals(k)))) {
node = e;
break;
}
p = e;
} while ((e = e.next) != null);
}
}
if (node != null && (!matchValue || (v = node.value) == value ||
(value != null && value.equals(v)))) {
if (node instanceof TreeNode)
((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
else if (node == p)
tab[index] = node.next;
else
p.next = node.next;
++modCount;
--size;
afterNodeRemoval(node);
return node;
}
}
return null;
}
这段代码是HashMap类中的一个私有方法,用于删除哈希表中的节点。具体解释如下:
方法签名:final Node
方法逻辑:
注意事项:
该方法用于HashMap的内部实现,用于删除哈希表中的节点。
删除操作需要经过哈希计算、键比较等步骤来找到要删除的节点。
删除节点可能涉及到链表的重组或红黑树的调整操作,以及在删除之后执行相应的后续操作。
HashMap是一个高效的数据结构,适用于存储大量的键值对。
在使用HashMap时,合理设置初始容量和负载因子,以及避免频繁的扩容操作,将有助于提高性能。