HashMap

本文详细探讨了HashMap的原理,包括与HashTable、TreeMap的区别,JDK1.7到1.8的改进,以及其重要的变量如加载因子。特别强调了JDK1.8中数组+链表+红黑树的实现,以及为何加载因子设为0.75的原因。此外,还介绍了HashMap的put和get操作、扩容机制以及遍历原理。
摘要由CSDN通过智能技术生成

目录

1.什么是HashMap?

1.1 HashMap与HashTable区别

1.2 JDK1.7前与JDK1.8下HashMap底层实现原理的区别

1.3 HashMap与TreeMap的区别

2.HashMap底层实现

2.1 数组+链表+红黑树的底层实现

2.2 jdk1.8以前HashMap存在的问题

2.3 解决方法-->JDK1.8底层实现

3.HashMap中重要的变量及问题

3.1 变量

3.2 问题

3.2.1 加载因子为什么默认值为0.75f ?

3.2.2 HashMap如何实现序列化和反序列化?

4.put源码

4.1 put操作过程总结

5.get源码

6.resize源码

7.遍历原理


1.什么是HashMap?

        HashMap基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

1.1 HashMap与HashTable区别

除表格中区别以外,HashMap类与HashTable大致相同

HashMap HashTable
多线程下不安全 多线程安全
ArrayList Vertor
键、值允许为null值(接收空值) 键、值为非null值(不接受控制)
实现不同步 实现同步

1.2 JDK1.7前与JDK1.8下HashMap底层实现原理的区别

JDK1.7前 JDK1.8
数组+链表 数组+链表+红黑树

1.3 HashMap与TreeMap的区别

HashMap TreeMap
底层实现:数组+链表+红黑树 底层实现:红黑树
键(key)、值(value)允许为null值 键(key)不允许为null
键(key)类型要一致

2.HashMap底层实现

2.1 数组+链表+红黑树的底层实现

  •  数组优点:通过数组下标可以快速实现对数组元素的访问,效率极高;
  •  链表优点:插入或删除数据不需要移动元素,只需修改节点的引用,效率极高。

源码

        数组-->HashMap使用数组存储数据,数组中每个元素的类型为Node<K,V> 。

static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;//键
        V value;//值
        Node<K,V> next;next指向链表的下一个节点

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

2.2 jdk1.8以前HashMap存在的问题

        HashMap通过 hash()&(n-1)-->key在数组中存放的下标。当两个key在数组中存放的下标一致时,数组将以链表方式存储(哈希冲突、哈希碰撞)。因而在链表查找一层层往下查找,知道找到,时间复杂度会O(N),所以链表长度越长,HashMap的效率会越来越低。

2.3 解决方法-->JDK1.8底层实现

        JDK1.8底层实现为数组+链表+红黑表来实现HashMap。即当链表中的元素超过8个(TREEIFY_THRESHOLD)并且数组长度大于64(MIN_TREEIFY_CAPACITY)时,会将链表转换为红黑树,转换后的数组查询时间复杂度为O(logN)。

源码

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // red-black tree links
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;    // needed to unlink next upon deletion
        boolean red;
        TreeNode(int hash, K key, V val, Node<K,V> next) {
            super(hash, key, val, next);
        }
        ......
}

3.HashMap中重要的变量及问题

3.1 变量

//数组的默认容量--16
static 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值