您的位置:首页 > 健康 > 养生 > 如何设置自己的网址_网站正能量免费下载_seo网站管理_优化视频

如何设置自己的网址_网站正能量免费下载_seo网站管理_优化视频

2025/2/24 17:39:08 来源:https://blog.csdn.net/qq_41934990/article/details/142829000  浏览:    关键词:如何设置自己的网址_网站正能量免费下载_seo网站管理_优化视频
如何设置自己的网址_网站正能量免费下载_seo网站管理_优化视频

在Java集合框架中,HashMap 是一种非常高效且常用的数据结构,它基于哈希表实现,提供了快速的查找、插入和删除操作。理解 HashMap 的内部机制不仅对于日常开发至关重要,而且对于优化应用程序性能也有着重要作用。本文将详细探讨 HashMap 的基本属性、构造方法以及其内部节点 Node 的实现细节。通过这些内容,读者可以更深入地了解 HashMap 的工作原理,并能够更好地利用它来解决实际问题。下面我们来一步步掌握它。

HashMap基础设置

public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {}

hashMap继承了AbstractMap抽象类实现了Map以及Cloneable和Serializable接口。

基础属性

//默认初始容量 - 必须是 2 的幂,最大为16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//最大容量,如果任一带有参数的构造函数隐式指定了更高的值,则使用。必须是 2 的幂 <= 1<<30
static final int MAXIMUM_CAPACITY = 1 << 30;//在 constructor 中未指定 None 时使用的载荷系数。
static final float DEFAULT_LOAD_FACTOR = 0.75f;//链表转换为红黑树的阈值。具体来说,当一个桶中的链表长度达到 TREEIFY_THRESHOLD 时,该链表会被转换为红黑树。
static final int TREEIFY_THRESHOLD = 8;//当一个红黑树的节点数减少到6或更少时,该红黑树会被重新转换为链表。
//原因:在节点数较少的情况下,链表的性能与红黑树相差不大,而且链表的内存占用更小,维护成本更低
static final int UNTREEIFY_THRESHOLD = 6;//只有当HashMap的容量(数组的长度)大于或等于64时,才会进行树化操作。
//为了避免在HashMap容量较小时进行不必要的树化操作。因为在容量较小时,哈希冲突的概率较低,链表长度达到8的情况较少见,直接使用链表已经足够高效。
static final int MIN_TREEIFY_CAPACITY = 64;//表,在首次使用时初始化,并根据需要调整大小。分配后,length 始终是 2 的幂
//存储HashMap中的所有键值对。每个数组元素(称为“桶”或“槽”),可以是一个链表的头结点或红黑树的根节点
transient Node<K,V>[] table;//该集合中包含所有的键值对条目
transient Set<Map.Entry<K,V>> entrySet;//记录当前HashMap中键值对的数量
transient int size;//记录HashMap结果被修改的次数。主要用于迭代器的快速失败机制,当迭代过程中检测到modCount发生变化时,会抛出ConcurrentModifocationException异常
transient int modCount;//阈值,表示进行扩容之前HashMap所能容纳的最大键值对数量。当size达到threshold时,HashMap会自动扩容
//计算方式:threshold = capacity * loadFactor,其中capacity是当前数组的容量
int threshold;//负载因子,用于控制HashMap的填充程度,默认通常是0.75
//负载因子决定了HashMap在何时进行扩容。较小的负载因子会导致更早的扩容。从而减少哈希冲突,但会增加内存消耗;加大的负载因子则相反
final float loadFactor;

构造方法

    //initialCapacity:初始容量,即HashMap在创建时分配的桶数组的大小//loadFactor:负载因子,用于控制HashMap的填充程度public HashMap(int initialCapacity, float loadFactor) {//校验初始容量是否合法(非负且不超过最大容量)if (initialCapacity < 0)throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;//校验负载因子是否合法(大于0且不是NaN)if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal load factor: " +loadFactor);//设置loadFactor和threshold(通过tableSizeFor方法计算出的值)this.loadFactor = loadFactor;this.threshold = tableSizeFor(initialCapacity);}//调用带有两个参数的构造方法,并使用默认的负载因子public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);}//使用默认的初始容量(通常是16)和默认的负载因子(通常是0.75)来创建HashMappublic HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}//m一个Map实例,从中复制所有的键值对到新的HashMap中//使用默认的负载因子,调用putMapEntries方法将m中的所有键值对添加到新的HashMap中public HashMap(Map<? extends K, ? extends V> m) {this.loadFactor = DEFAULT_LOAD_FACTOR;putMapEntries(m, false);}//m要复制的Map//evict是否在插入过程中执行驱逐操作(通常用于LinkedHashMap)final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {//获取m的大小int s = m.size();if (s > 0) {//如果table为空(即HashMap还未初始化),则根据m的大小和负载因子预先调整HashMap的容量if (table == null) { // pre-sizefloat ft = ((float)s / loadFactor) + 1.0F;int t = ((ft < (float)MAXIMUM_CAPACITY) ?(int)ft : MAXIMUM_CAPACITY);if (t > threshold)threshold = tableSizeFor(t);}//如果m的大小超过当前的threshold,则进行扩容else if (s > threshold)resize();//遍历m的所有条目,将每个条目插入到HashMap中,调用putVal方法进行实际的插入操作for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {K key = e.getKey();V value = e.getValue();putVal(hash(key), key, value, false, evict);}}}

基础结构

以下代码定义了HashMap中的一个静态内部类Node,实现了Map.Entry<K,V>接口。用于表示HashMap中的每个键值对节点。

static class Node<K,V> implements Map.Entry<K,V> {final int hash;//存储建的哈希码,用于快速查找final K key;//存储键,标记为final,表示一旦创建不能更改V value;//存储值Node<K,V> next;//指向下个节点的引用,用户处理哈希冲突时形成的链表或红黑树Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}//获取当前节点的keypublic final K getKey()        { return key; }//获取当前节点的valuepublic final V getValue()      { return value; }public final String toString() { return key + "=" + value; }//计算并返回键和值的哈希码的异或结果,Objects.hashCode()方法会处理null值的结果public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}//设置当前节点的值更新为newValue,并发挥旧值public final V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}//比较相等性public final boolean equals(Object o) {//如果是对象本身,直接返回trueif (o == this)return true;//如果对象是Map.Entry的实例,则比较键和值是否都相等//使用Objects.equals()来处理null值的情况if (o instanceof Map.Entry) {Map.Entry<?,?> e = (Map.Entry<?,?>)o;if (Objects.equals(key, e.getKey()) &&Objects.equals(value, e.getValue()))return true;}//都不相等,返回falsereturn false;}}

通过本文的深入探讨,我们揭开了 HashMap 的内部机制和关键特性。理解这些基础知识不仅能够帮助你在日常开发中更高效地使用 HashMap,还能在面对性能优化问题时提供有力的支持。希望这篇文章为你提供了有价值的见解,并能够在你的编程之旅中发挥重要作用。如果你有任何疑问或需要进一步的帮助,请随时留言交流。祝你在 Java 开发道路上不断进步,取得更大的成就!
更多精彩内容请关注以下公众号
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com