加入收藏 | 设为首页 | 会员中心 | 我要投稿 马鞍山站长网 (https://www.0555zz.cn/)- 媒体处理、内容创作、云渲染、网络安全、业务安全!
当前位置: 首页 > 综合聚焦 > 编程要点 > 资讯 > 正文

彻底搞懂hashMap底层特点

发布时间:2023-10-18 13:17:07 所属栏目:资讯 来源:
导读:Java 1.7和1.8版本的哈希表有所改进,我们本篇只说java1.7的hashMap。

hashMap的数据结构是由数组和链表组成,table是一个存放Entry对象的数组,每个Entry对象由4个属性组成,分别是key、value、next、hash,ke

Java 1.7和1.8版本的哈希表有所改进,我们本篇只说java1.7的hashMap。

hashMap的数据结构是由数组和链表组成,table是一个存放Entry对象的数组,每个Entry对象由4个属性组成,分别是key、value、next、hash,key和value是我们熟知的键值对,不需要过多解释,next是当前元素在链表中指向下一个元素的引用,hash是计算出来的hashcode,hashMap中的hsah是通过对key.hashcode()进行一定操作得出的,并不是直接使用key.hashcode()方法计算数来的值。

先来了解下hashMap中一些重要的属性:

复制
//Hashmap的初始化大小,初始化的值为16,1往右移4位为16
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 

//HashMap是动态扩容的,就是容量大小不能大于 1<<30
static final int MAXIMUM_CAPACITY = 1 << 30;

//默认的扩容因子,这个值可以通过构造修改
static final float DEFAULT_LOAD_FACTOR = 0.75f;

//空数据,默认构造的时候赋值为空的Entry数组,在添加元素的时候
//会判断table=EMPTY_TABLE ,然后就扩容
static final Entry<?,?>[] EMPTY_TABLE = {};

//表示一个空的Hashmap
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

//Hashmap的大小
transient int size;

//threshold表示当HashMap的size大于threshold时会执行resize操作。
DEFAULT_INITIAL_CAPACITY=16

//扩容的阈值
int threshold;

//扩容因子,没有传入就使用默认的DEFAULT_LOAD_FACTOR = 0.75f
final float loadFactor;

//数据操作次数,用于迭代检查修改异常
transient int modCount;

static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

四、put方法
步骤:

判断table是否为空,如果为空则初始化,不为空则下一步
判断key是否为null,如果为null则处理,不为null则下一步
根据key计算下标
如果下标处的桶不为最大的空,则从第一行的下标处位置开始遍历第一行的链表,如果找到key相同的则更新第一行覆盖并返回相应的旧值,如果为空则下一步
插入前判断是否需要扩容,如果需要则进行扩容,如果不需要就下一步
头插法插入桶中
接下来我们对每一步骤分别展开讨论。

1.table初始化
复制
private void inflateTable(int toSize) {
    // 找到大于等于指定数组长度的2的n次方
    int capacity = roundUpToPowerOf2(toSize);
 // 扩容阈值,数组长度*负载因子
    threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
    // 创建数组
    table = new Entry[capacity];
    // 是否重新赋值hashSeed 
    initHashSeedAsNeeded(capacity);
}

private static int roundUpToPowerOf2(int number) {
    // 使用Integer的highestOneBit方法找到大于等于指定数组长度的2的n次方
    return number >= MAXIMUM_CAPACITY
            ? MAXIMUM_CAPACITY
            : (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}

数组初始化其实就三个步骤:计算数组容量,创建数组,判断是否重hash。下面我们一起来看看如何创建数组容量。

(编辑:马鞍山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章