JAVA进阶篇——一行代码一行代码嚼烂之超详细注解手写HashMap(二

Entry<K, V>[] table;

public K put(K key, V value) {

Entry<K, V> newEntry = new Entry(key, value);

// 这里我们没有写可以手动输入初始值的方法,所以直接设置默认容量

if (table == null) {

table = new Entry[INITIAL_CAPACITY];

}

// 数组下标位置

int hash = hash(key);

// 链表模型,如果Hash值相等,则形成链表

// head代表链表头,此处用的头插法

Entry<K, V> head = table[hash];

// 当容量达到初始容量的加载因子时扩容

if(COUNT > table.length * LOAD_FACTOR){

resize();

}

// 注意数组+链表的概念模型将会再这里产生

// 如果table[hash]这个位置没有元素,直接赋值

if (head == null) {

table[hash] = newEntry;

COUNT++;

return key;

} else {

// 如果table[hash]这个位置有元素

Entry tail = new Entry<K, V>();

// 如果这个元素的next指针为空,设置指针指向新的键值

if (head.next == null) {

head.next = newEntry;

} else {

// 如果指针next不为空,找到指针为空的链表上的那一个元素,插入

do {

tail = head;

} while ( (head = head.next) != null );

// 该链表上此对象的指针指向新的对象

tail.next = newEntry;

}

COUNT++;

return key;

}

}

到这里中途打断一下,为了更深度地帮助各位理解HashMap数组+链表的结构,这里我画了一张图帮助理解:

JDK1.7HashMap头插法

继续:

/** 扩容*/

public int resize() {

// 扩容, << 2 代表 4倍 扩容

int newCapacity = INITIAL_CAPACITY << 2;

// 新建一个数组

Entry[] newTable = new Entry[newCapacity];

// 数组的copy方法

System.arraycopy(table, 0, newTable, 0, table.length);

// 新数组赋值给老数组

this.table = newTable;

// 返回新容量

return newCapacity;

}

/** 获取 key 的键值*/

public V get(K key) {

Entry<K, V> entry;

// 二元表达式通过getEntry()方法寻找键值

return (entry = getEntry(hash(key), key)) == null ? null : entry.value;

}

/** 传入 hash 获取 key 值*/

public Entry<K, V> getEntry(int hash, K key) {

// 新建对象做逻辑判断

Entry<K, V> entry = table[hash];

// 如果 table[hash] 为空,证明不存在此 key 的键值

if (entry == null) {

return null;

} else if (entry != null && entry.next == null) {

// 如果此元素不为空,并且此元素的next指针为空,证明此链表上只有一个元素,直接返回

return entry;

} else if (entry.next != null) {

// 如果此对象的 next 指针不为空,就要在此链表上去找到 hash 值相等的数据

do {

// 如果此元素的hash与该对象的key值的hash相等

// 并且

// key相等 或者 key不为空并且key相等

if (hash == hash(entry.key) && (key == entry.key || (key != null && key.equals(entry.key)))) {

// 返回此链表上的对象

return entry;

}

// 条件是此对象的指针 next 不为空

} while ( (entry = entry.next) != null );

// 如果通过以上循环没有找到对象的对像的话,返回空

return null;

}

return null;

}

/** 计算hash*/

public final int hash(K key) {

// &运算:4 & 5

// 转化为二进制: 100 & 101 = 100 (同时为1才为1,否则为0)

// 十进制:4

// 所以: 4 & 5 = 4

//

// 0x7FFFFFFF代表int的最大值

//

// 此操作主要是为了取得正整数

//

// 后面 %运算 是为了使得返回值数组下标不会越界,即返回值小于数组或者扩容后数组的大小

return (key == null) ? 0 : ( key.hashCode() & 0x7FFFFFFF % table.length);

}

/** 返回 map 集合大小的方法*/

public int size(){

return COUNT;

}

}

测试类


package com.gantiexia.hashmap;

/**

  • 测试 MyHashMap

  • @author GanTieXia

  • @date 2021/9/27 21:29

*/

public class TestMyHashMap {

public static void main(String[] args) {

HashMap<String,String> map = new HashMap<>();

map.put(“GanTieXia”,“肝铁侠”);

map.put(“ZhuZhuXia”,“猪猪侠”);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

义、实战项目、讲解视频,并且后续会持续更新**

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-45JFCAjG-1711959369083)]

最后

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习

已经将知识体系整理好(源码,笔记,PPT,学习视频)

[外链图片转存中…(img-kdkBrQq0-1711959369083)]

[外链图片转存中…(img-UVFFqrZ2-1711959369084)]

[外链图片转存中…(img-XOOn68YY-1711959369084)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值