1. HashMap源码:内部结构初看

hashmap的内部结构

hashmap由两部分组成,桶数组table和链表/红黑树。桶数组就是个数组,每个元素都是一个链表的头节点。链表的节点就是键值对,根据每一处链表长度来决定其是单向链表还是红黑树。

transient Node<K,V>[] table      // 容量总是2的整数幂,原因在于每次扩容resize需要划分链表/树,高链表下标是旧数组长度+旧数组下标,所以新数组长度要是旧数组*2,初始数组长度是16,所以一定是2的整数幂。可见resize方法。

单链表节点(篇幅原因仅看主要的方法)

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash; // 这个hash值只考虑键
    final K key; // final:说明节点的key不可变
    V value;     //value值可以被替换
    Node<K,V> next; // 指向下一个节点,形成单链表

    public final String toString() { return key + "=" + value; }

    public final int hashCode() { // 同时考虑键和值
        return Objects.hashCode(key) ^ Objects.hashCode(value);
    }
	// key相同时,用新值替换旧值(value),返回旧值
    public final V setValue(V newValue) {
        V oldValue = value;
        value = newValue;
        return oldValue;
    }
	// eqals:同类相同对象,返回true;不同类但是也实现entry接口时,如果key和value指向地址相同也返回true。
    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;
    }
}

红黑树节点:

LinkedHashMap.Entry继承HashMap.Node<K,V>,所以其实红黑树节点继承单链表节点,可以实现单链表向下强制转换为红黑树节点:(TreeNode<K,V>)

static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
        TreeNode<K,V> parent;  // 树节点关系包括父节点、左右孩子节点、前向节点和后向节点(next,继承Node)
        TreeNode<K,V> left;
        TreeNode<K,V> right;
        TreeNode<K,V> prev;    
        boolean red; // 节点颜色
        TreeNode(int hash, K key, V val, Node<K,V> next) {
            super(hash, key, val, next);
        }
    ...}

hashmap里的属性

主要和容量(指的是table数组长度)有关,关系到是否扩容或者红黑树化或者链表化。

// 默认初始容量16 二进制向左移位4
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 
// 最大容量
static final int MAXIMUM_CAPACITY = 1 << 30;  
// 默认负载因子0.75
static final float DEFAULT_LOAD_FACTOR = 0.75f; 
// 数组中某元素,也就是链表,上的节点数目大于该属性,该处链表转为红黑树
static final int TREEIFY_THRESHOLD = 8;  
// 数组中某元素,也就是链表,上的节点数目小于该属性,该处红黑树转化为链表
static final int UNTREEIFY_THRESHOLD = 6; 
// 当桶的数组大小小于64的是偶,优先扩容,而不是转化为红黑树,也就是桶大小超过64后才会开始生成红黑树
static final int MIN_TREEIFY_CAPACITY = 64; 

// 数组存放的键值对的数量
transient int size;
// 扩容和更改map结构的计数器,更新旧值不会增加
transient int modCount;
// 阈值 当实际大小(容量*负载因子)超过该阈值时,会进行扩容
int threshold;
// 负载因子 一旦初始化,便不能更改
final float loadFactor;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值