HashMap源码--(五)Entry

HashMap源码–(五)Entry

HashMap继承了Map,HashMap.Entry实现了Map.Entry类,并实现了Entry类里的方法。
Entry的实现是一个链表。它的属性包括key、value、next、hash。
HashMap存数据是以key-value的键值对方式,实际HashMap存的是Entry数组,key-value就是Entry对象key和value属性。
Entry类的属性和构造器如下:

static class Entry<K,V> implements Map.Entry<K,V> {
        final K key;
        V value;
        Entry<K,V> next;
        final int hash;

        /**
         * Creates new entry.
         */
        Entry(int h, K k, V v, Entry<K,V> n) {
            value = v;
            next = n;
            key = k;
            hash = h;
        }
}

这里的key是用final定义的,可以看出对于Entry对象来说,key值只能被赋值一次。key也可以赋null。key主要的作用就是用于计算哈希值得出存放位置,使数据快速存取。上面说了HashMap中存放的就是Entry,那在HashMap在存值时,由于key值是final的,不能再次被赋值,所以会先匹配key值是否存在,如果存在,则key对应的Entry对象的value将被覆盖,如果不存在,则创建Entry对象。HashMap取值时,根据key来取值的方式最常用。
Entry类中包含了获取key和value的方法,也包括equals、hashCode、toString,Entry还有两个没有方法内容的方法,如下:

        public final K getKey() {return key;}
        public final V getValue() {return value;}
        public final V setValue(V newValue) {
        V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry e = (Map.Entry)o;
            Object k1 = getKey();
            Object k2 = e.getKey();
            if (k1 == k2 || (k1 != null && k1.equals(k2))){
                Object v1 = getValue();
                Object v2 = e.getValue();
                if (v1 == v2 || (v1 != null && v1.equals(v2)))
                    return true;
            }
            return false;
        }

        public final int hashCode() {
            return (key==null   ? 0 : key.hashCode()) ^
                   (value==null ? 0 : value.hashCode());
        }

        public final String toString() {return getKey() + "=" + getValue();}

        /**
         * 该方法用于key值存在,value被覆盖时
         */
        void recordAccess(HashMap<K,V> m) {}
        /**
         * 该方法用于entry被移除时
         */
        void recordRemoval(HashMap<K,V> m) {}

对Entry操作的方法有addEntry、createEntry等,这些操作方法可以看出Entry链表的存储方式,如下:

    /**
     *添加Entry
    */
    void addEntry(int hash, K key, V value, int bucketIndex) {
        //在Entry数组table中获取bucketIndex位置的数据
        Entry<K,V> e = table[bucketIndex];
        //向table数组bucketIndex位置添加Entry对象
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        //调整数组大小
        if (size++ >= threshold)
            resize(2 * table.length);
    }

    /**
     *创建Entry
    */
    void createEntry(int hash, K key, V value, int bucketIndex) {
        //在Entry数组table中获取bucketIndex位置的数据
    Entry<K,V> e = table[bucketIndex];
    //向table数组bucketIndex位置添加Entry对象
        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
        size++;
    }

addEntry放在put方法添加数据时使用,是根据给定的key、value、hash添加到Entry数组table的bucketIndex位置。要向数组中加数据,这个方法也需要负责resize数组的大小length。当然如果想改变HashMap的put数据的方式,需要重写这个方法。table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
这段代码是向table数组加Entry对象,这个Entry的next指向table数组的bucketIndex位置。
createEntry同addEntry很像,但它只是向数组赋值,不调整大小。在HashMap构造器使用。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页