IdentityHashMap类源码解析

IdentityHashMap使用数组存储键值对,键值对相邻,冲突时采用线性探测。它基于引用相等而非对象相等来判断key是否相同,区别于HashMap。默认加载因子为2/3,超过该因子与容量乘积时会扩容到原容量的2倍。它继承AbstractMap,实现了Map、Serializable和Cloneable接口。
摘要由CSDN通过智能技术生成

IdentityHashMap
1.内部通过数组存储键值对,相邻元素存在键值对
比如:i 位置是key,i+1位置是value
2.当hashcode相等,出现冲突的时候,通过线性探索发解决冲突问题
3.比较的是引用相等
IdentityHashMap与常用的HashMap的区别是:
前者比较key时是“引用相等”而后者是“对象相等”,即对于k1和k2,当k1==k2时,IdentityHashMap认为两个key相等,而HashMap只有在k1.equals(k2) == true 时才会认为两个key相等。
默认的加载因子为2/3,在重新哈希后,加载因子变为1/3.当哈希表中的条目数超出了加载因子与当前容量的乘积时,通过调用 reszie 方法将容量翻倍,重新进行哈希。增加桶数,重新哈希,可能相当昂贵。

继承AbstractMap
实现Map、java.io.Serializable、Cloneable



package java.util;
import java.io.*;


public class IdentityHashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, java.io.Serializable, Cloneable
{
    /**
     * 默认容量
     */
    private static final int DEFAULT_CAPACITY = 32;

    /**
     * 最小容量
     */
    private static final int MINIMUM_CAPACITY = 4;

    /**
     * 最大容量
     */
    private static final int MAXIMUM_CAPACITY = 1 << 29;

    /**
     * 输出存储结构
     */
    private transient Object[] table;

    /**
     * 键值对个数
     * @serial
     */
    private int size;

    /**
     * 修改次数
     */
    private transient int modCount;

    /**
     * 更新容器时候的阈值= (capacity * load factor).
     */
    private transient int threshold;

    /**
     * Value representing null keys inside tables.
     */
    private static final Object NULL_KEY = new Object();

    /**
     * Use NULL_KEY for key if it is null.
     */
    private static Object maskNull(Object key) {
        return (key == null ? NULL_KEY : key);
    }

    /**
     * Returns internal representation of null key back to caller as null.
     */
    private static Object unmaskNull(Object key) {
        return (key == NULL_KEY ? null : key);
    }

    /**
     * 构造函数
     */
    public IdentityHashMap() {
        init(DEFAULT_CAPACITY);
    }

    /**
     * 构造函数
     *
     * @param expectedMaxSize the expected maximum size of the map
     * @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
     */
    public IdentityHashMap(int expectedMaxSize) {
        if (expectedMaxSize < 0)
            throw new IllegalArgumentException("expectedMaxSize is negative: "
                                               + expectedMaxSize);
        init(capacity(expectedMaxSize));
    }

    /**
     * Returns the appropriate capacity for the specified expected maximum
     * size.  Returns the smallest power of two between MINIMUM_CAPACITY
     * and MAXIMUM_CAPACITY, inclusive, that is greater than
     * (3 * expectedMaxSize)/2, if such a number exists.  Otherwise
     * returns MAXIMUM_CAPACITY.  If (3 * expectedMaxSize)/2 is negative, it
     * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
     */
    private int capacity(int expectedMaxSize) {
        // Compute min capacity for expectedMaxSize given a load factor of 2/3
        int minCapacity = (3 * expectedMaxSize)/2;

        // Compute the appropriate capacity
        int result;
        if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
            result = MAXIMUM_CAPACITY;
        } else {
            result = MINIMUM_CAPACITY;
            while (result < minCapacity)
                result <<= 1;
        }
        return result;
    }

    /**
     * init
     */
    private void init(int initCapacity) {
        // assert (initCapacity & -initCapacity) == initCapacity; // power of 2
        // assert initCapacity >= MINIMUM_CAPACITY;
        // assert initCapacity <= MAXIMUM_CAPACITY;

        threshold = (initCapacity * 2)/3; // 进行扩容时候的阈值
        table = new Object[2 * initCapacity]; // 2倍,表示key value相邻存储
    }

    /**
     * 构造函数,m集合元素加入到当前集合中
     */
    public IdentityHashMap(Map<? extends K, ? extends V> m) {
        // Allow for a bit of growth
        this((int) ((1 + m.size()) * 1.1));
        putAll(m);
    }

    /**
     * size
     */
    public int size() {
        return size;
    }

    /**
     * isEmpty
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Returns index for Object x.
     */
    private static int hash(Object x, int length) {
        int h = System.identityHashCode(x);
        // Multiply by -127, and left-shift to use least bit as part of hash
        return ((h << 1) - (h << 8)) & (length - 1);
    }

    /**
     *循环的方式,找到下一个key的id 
     */
    private static int nextKeyIndex(int i, int len) {
        return (i + 2 < len ? i + 2 : 0);
    }

    /**
     * V get(Object key)
     */
    public V get(Object key) {
        Object k = maskNull(key);
        Object[] tab = table;
        int len = tab.length;
        int i = hash(k, len); // 根据hash计算应该在数组中的id 
        while (true) {
            Object item = tab[i]; // 当前key 
            if (item == k) // 比较是否相等,相等下一个位置就是value 
                return (V) tab[i + 1];
            if (item == null)
                return null;
            i = nextKeyIndex(i, len); // 上面不满足,根据上一个i 更新 i 
        }
    }

    /**
     * containsKey 和  get 很类似 
     */
    public boolean containsKey(Object key) {
        Object k = maskNull(key);
        Object[] tab = table;
        int len = tab.length;
        int i = hash(k, len);
        while (true) {
            Object item = tab[i];
            if (item == k)
                return true;
            if (item == null)
                return false;
            i = nextKeyIndex(i, len);
        }
    }

    /**
     * containsValue
     */
    public boolean containsValue(Object value) {
        Object[] tab = table;
        for (int i = 1</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值