共同学习Java源代码-数据结构-HashMap(十二)

来源:互联网 发布:怎么成为大数据分析师 编辑:程序博客网 时间:2024/06/10 18:21

中间略过一些lambda表达式相关方法 以后再说

    @SuppressWarnings("unchecked")
    @Override
    public Object clone() {
        HashMap<K,V> result;
        try {
            result = (HashMap<K,V>)super.clone();
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
        result.reinitialize();
        result.putMapEntries(this, false);
        return result;
    }

这个是克隆方法先调用父类的克隆方法 然后调用reinitialize方法清空所有数据 然后将本对象的数据填充进去 然后返回新的克隆体


    final float loadFactor() { return loadFactor; }
   这个方法返回载荷    


    final int capacity() {
        return (table != null) ? table.length :
            (threshold > 0) ? threshold :
            DEFAULT_INITIAL_CAPACITY;
    }

 这个方法返回的是容量 判断哈希桶数组是否为空 如果不为空就返回哈希桶数组的长度 如果为空 再判断扩容门槛大于0么 如果大于0 就返回扩容门槛 否则返回默认初始容量也就是16 


    private void writeObject(java.io.ObjectOutputStream s)
        throws IOException {
        int buckets = capacity();
        // Write out the threshold, loadfactor, and any hidden stuff
        s.defaultWriteObject();
        s.writeInt(buckets);
        s.writeInt(size);
        internalWriteEntries(s);
    }

这个方法是序列化输出的时候 将本对象输出到流的方法 不多说了 将本对象的容量 键值对数目以及键值对都写到输出流里


   private void readObject(java.io.ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        // Read in the threshold (ignored), loadfactor, and any hidden stuff
        s.defaultReadObject();
        reinitialize();
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new InvalidObjectException("Illegal load factor: " +
                                             loadFactor);
        s.readInt();                // Read and ignore number of buckets
        int mappings = s.readInt(); // Read number of mappings (size)
        if (mappings < 0)
            throw new InvalidObjectException("Illegal mappings count: " +
                                             mappings);
        else if (mappings > 0) { // (if zero, use defaults)
            // Size the table using given load factor only if within
            // range of 0.25...4.0
            float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
            float fc = (float)mappings / lf + 1.0f;
            int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
                       DEFAULT_INITIAL_CAPACITY :
                       (fc >= MAXIMUM_CAPACITY) ?
                       MAXIMUM_CAPACITY :
                       tableSizeFor((int)fc));
            float ft = (float)cap * lf;
            threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                         (int)ft : Integer.MAX_VALUE);
            @SuppressWarnings({"rawtypes","unchecked"})
                Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
            table = tab;


            // Read the keys and values, and put the mappings in the HashMap
            for (int i = 0; i < mappings; i++) {
                @SuppressWarnings("unchecked")
                    K key = (K) s.readObject();
                @SuppressWarnings("unchecked")
                    V value = (V) s.readObject();
                putVal(hash(key), key, value, false, false);
            }
        }
    }

这个方法是反序列化时从流中读取HashMap的方法

先调用输入流的方法读入流中对象

然后调用reinitialize方法重新将本对象清空

然后判断载荷是否合法 小于0或为nan 直接抛出异常

然后调用readInt方法读入容量 然后不赋值给任何变量 

然后调用readInt方法读入键值对数目 判断如果键值对数目小于0 就抛出异常

如果键值对数目大于0 就计算扩容门槛

先计算0.25f和载荷的最大值 然后将这个最大值和4.0f比最小值 得到的值赋给lf变量

然后将键值对数目除以lf再加一 得到fc

然后判断fc是否小于16 如果小于16就取16赋值给cap变量 如果fc大于2的30次方就取2的30次方给cap 如果fc在16和2的30次方之间 就调用tableSizeFor方法计算出cap 

然后cap乘以1f得出ft 

然后判断cap和ft都是否小于2的30次方 如果都小于 就取cap为扩容门槛 如果有一个不小于 就取2的31次方-1为扩容门槛

然后构建哈希桶数组 长度为cap 然后遍历键值对 将键值对通过putval方法填充进去




阅读全文
0 0
原创粉丝点击