手撕HashMap底层源码 (JDK1.7版本的HashMap)

day27

集合框架

标绿已经学习底层,深入底层主要是研究实现类底层集合框架

手撕HashMap底层源码

JDK1.7版本的HashMap

切换版本

原因:jdk1.7和jdk1.8的HashMap不同(头插法/尾插法)

首先如果没有jdkjre1.7,就安装jdkjre1.7,之后eclipse中添加
添加jre1.7
由于前期都用的jdk1.8版本,所有要再切换jdk1.7版本
转换jre1.7

场景:
		HashMap<Student, String> map = new HashMap<>();
		map.put(new Student("小小", '男', 23, "2401", "001"), "拍电影");
		map.put(new Student("大大", '男', 20, "2401", "002"), "打篮球");
		map.put(new Student("奇男子", '男', 21, "2401", "003"), "玩游戏");
		map.put(new Student("奇男子", '男', 21, "2401", "003"), "写代码");
		map.put(null, "aaa");
		map.put(null, "bbb");
遍历:数组从头到尾遍历
        null=bbb
        奇男子	男	21	2401	003=写代码
        大大	男	20	2401	002=打篮球
        小小	男	23	2401	001=拍电影
补充:NaN - Not a Number
//		Float float1 = new Float("0.0f");
//		Float float2 = new Float("0.0f");
//		Float result = float1/float2;
//		System.out.println(result);//NaN
//		System.out.println(Float.isNaN(result));
//		HashMap<Student, String> map = new HashMap<>(16,result);

底层

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>{
    //默认初始化容量 -- 必须是2的幂
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
    //最大容量
    static final int MAXIMUM_CAPACITY = 1 << 30;
    //默认的负载因子(静态属性共享,也可以添加自定义负载因子)
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    //空内容的数组
    static final Entry<?,?>[] EMPTY_TABLE = {};
    //hash数组/hash表
    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;//EMPTY_TABLE
    //元素个数
    transient int size;//0
    //阈值(数组长度*负载因子)
    int threshold;//16
    //负载因子
    final float loadFactor;//0.75f
    //外部操作数(记录添加、删除的次数)
    transient int modCount;//0
    //hash种子数
    transient int hashSeed = 0;//0
    
    public HashMap() {
        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }
    
    //initialCapacity - 16
    //loadFactor - 0.75f
    public HashMap(int initialCapacity, float loadFactor) {
        //判断数组初始化容量如果小于0,就报错
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        
        //判断数组容量大于最大容量,就把最大容量赋值给初始化容量
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        
        //判断负载因子如果小于等于0 或者 判断负载因子不是一个数字,就报错
        if (loadFactor <= 0 || Float.isNaN(loadFactor))//NaN - Not a Number
            throw new IllegalArgumentException("Illegal load factor: " + loadFactor);

        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();//作用:让子类去重写(LinkedHashMap),子类做初始化功能
    }
    
    void init() {
    }
    
    //映射关系类/节点类
    static class Entry<K,V> implements Map.Entry<K,V> {
        final K key; --------- key
        V value; ------------- value
        Entry<K,V> next; ----- 下一个节点的地址
        int hash; ------------ key的hash值

        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }
     }
}
HashMap理解图

HashMap理解图

init();的作用

让子类去重写(LinkedHashMap),子类做初始化功能
伪代码理解:LinkedHashMap调用父类的有参构造,int()返过来调用子类LinkedHashMap中重写的int();
int伪代码

面试题

JDK1.7版本的HashMap是什么数据结构?

一维数组+单向链表

什么是Hash桶?

hash数组里的单向链表

什么是hash碰撞/hash冲突?

key的hash值一致,在数组中的下标上有重复的元素

HashMap默认数组长度是多少?

长度是1<<4,就是16的长度

HashMap数组的长度为什么必须是2的幂?

??????(涉及后面内容先搁置)

HashMap数组的最大容量是多少?

1<<30

HashMap数组的最大容量为什么是1<<30?

最大容量为int类型,int类型的最大值是2的31次方-1

因为HashMap数组必须是2的幂,1<<30是int取值范围内最大的2的幂的数字

所以HashMap数组最大容量是1<<30

HashMap默认负载因子是多少?

0.75f

HashMap的负载因子的作用是什么?

数组长度*负载因子 等于 阈值,阈值是控制何时扩容

HashMap数组默认的负载因子为什么是0.75f?

取得了空间和时间的平衡

如果负载因子过大(如:1),会导致数组全部装满后,再扩容。利用了空间,浪费了时间

如果负载因子过小(如:0.2),会导致数组装了一点点元素,就扩容。利用了时间,浪费了空间

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值