Java7/8集合框架——HashMap

java.util.HashMap

  Java7/8中HashMap(和 ConcurrentHashMap)的相关基本操作源码介绍,这里可以直接参考【Java7/8中的 HashMap 和 ConcurrentHashMap 全解析,介绍得还是挺详细的,就不班门弄斧了。

  关于Java7的HashMap,这里主要提几点,具体的分析还是请参考上面给的链接,

  1. Java7中HashMap源码的大方向就是:数组 + 单向链表(数组的元素,Entry 实例,包含四个属性:key, value, hash 值和用于单向链表的 next),对于hash冲突的元素,使用链表进行存储,每次存储在链表头,操作也比较快。
  2. capacity:当前数组容量,默认值是16,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
  3. loadFactor:负载因子,默认为 0.75。
  4. threshold:扩容的阈值,等于 capacity * loadFactor,当元素实际个数size大于等于threshold时,进行扩容。

  Java8的HashMap,最大的改变,是使用了数组+链表+红黑树。当链表中的元素达到了 8 个时,会将链表转换为红黑树,在这些位置进行查找的时候可以由原来的耗时O(N),降低时间复杂度为 O(logN)。

  关于红黑树和ConcurrentHashMap,有待后续的进一步研究。

  另外还要提到的是,关于HashMap中的一些扩展点。

1、init()方法:在LinkedHashMap,该方法用于进行虚结点的初始化。

    /**
     * Constructs an empty <tt>HashMap</tt> with the specified initial
     * capacity and load factor.
     *
     * @param  initialCapacity the initial capacity
     * @param  loadFactor      the load factor
     * @throws IllegalArgumentException if the initial capacity is negative
     *         or the load factor is nonpositive
     * HashMap中的方法
     */
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        this.loadFactor = loadFactor;
        threshold = initialCapacity;
        init();
    }
    /**
     * Called by superclass constructors and pseudoconstructors (clone,
     * readObject) before any entries are inserted into the map.  Initializes
     * the chain.
     * LinkHashMap中重写之后的方法
     */
    @Override
    void init() {
        header = new Entry<>(-1, null, null, null);
        header.before = header.after = header;
    }

2、Entry的recordAccess方法:HashMap中是空实现,从名字可以看出“记录访问”,在LinkedHashMap中进行了重写,用于根据插入或者访问元素的顺序来调整链表元素。

        /**
         * This method is invoked whenever the value in an entry is
         * overwritten by an invocation of put(k,v) for a key k that‘s already
         * in the HashMap.
         * HashMap中Entry的方法
         */
        void recordAccess(HashMap<K,V> m) {
        }

        // 以下的是LinkedHashMap中Entry的方法
        /**
         * Removes this entry from the linked list.
         */
        private void remove() {
            before.after = after;
            after.before = before;
        }

        /**
         * Inserts this entry before the specified existing entry in the list.
         */
        private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
        }

        /**
         * This method is invoked by the superclass whenever the value
         * of a pre-existing entry is read by Map.get or modified by Map.set.
         * If the enclosing Map is access-ordered, it moves the entry
         * to the end of the list; otherwise, it does nothing.
         */
        void recordAccess(HashMap<K,V> m) {
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
        }

  另外还有几个点,如get(Object key)、addEntry(int hash, K key, V value, int bucketIndex)、createEntry(int hash, K key, V value, int bucketIndex)等,在LinkedHashMap中都进行了重写,用于支持根据插入或者访问元素的顺序来调整链表元素,LinkedHashMap相关的控制变量源码如下,这里大致说明下操作的顺序:

  1. 所有的插入元素的操作都是调用:put(K key, V value)
  2. 如果key已经存在,表明需要更改对应的value,此时不会增加元素,更改value时,都会调用Entry.recordAccess方法
  3. recordAccess中,会根据accessOrder调整访问的元素,当accessOrder = true时,表示按照访问顺序调整,把刚才访问到的元素挪到链表最后,若accessOrder = false,则按照插入元素的顺序,由于不涉及到插入元素,因此不进行操作
  4. 如果key不存在,则都会调用addEntry方法,这个时候,元素都是在链表最后,因此不用进行额外的操作。
  5. addEntry中还调用了removeEldestEntry,用于判断是否要移除最后访问或者插入的元素。这个是实现LRU的一个点。

相关具体说明后续在介绍LinkedHashMap时会进一步细讲。

    /**
     * The iteration ordering method for this linked hash map: <tt>true</tt>
     * for access-order, <tt>false</tt> for insertion-order.
     *
     * @serial
     */
    private final boolean accessOrder;        //true表示按照访问顺序,默认false表示按照插入顺序,调整特定元素至尾部

原文地址:https://www.cnblogs.com/wpbxin/p/8684747.html

时间: 2024-08-30 14:08:47

Java7/8集合框架——HashMap的相关文章

java源码分析之集合框架HashMap 10

HashMap HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口. HashMap 的实现不是同步的,这意味着它不是线程安全的.它的key.value都可以为null.此外,HashMap中的映射不是有序的. HashMap 的实例有两个参数影响其性能:"初始容量" 和 "加载因子".容量 是哈希表中桶的数量,初

day18&lt;集合框架+&gt;

集合框架(Map集合概述和特点) 集合框架(Map集合的功能概述) 集合框架(Map集合的遍历之键找值) 集合框架(Map集合的遍历之键值对对象找键和值) 集合框架(Map集合的遍历之键值对对象找键和值源码分析) 集合框架(HashMap集合键是Student值是String的案例) 集合框架(LinkedHashMap的概述和使用) 集合框架(TreeMap集合键是Student值是String的案例) 集合框架(统计字符串中每个字符出现的次数) 集合框架(集合嵌套之HashMap嵌套Hash

Java集合框架(四)_day18

18.集合框架(Map集合概述和特点) A:Map接口概述 查看API可以知道: 将键映射到值的对象 一个映射不能包含重复的键 每个键最多只能映射到一个值 B:Map接口和Collection接口的不同 Map是双列的,Collection是单列的 Map的键唯一,Collection的子体系Set是唯一的 Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效 18.集合框架(Map集合的功能概述) A:Map集合的功能概述 a:添加功能 V put(K

java集合框架小结(进阶版)之HashMap篇

基本概念: Hash(哈希):hash一般也译作“散列”.事实上,就是一个函数,用于直接定址.将数据元素的关键字key作为变量,通过哈希函数,计算生成该元素的存储地址. 冲突:函数是可以多对一的.即:多个自变量可以映射到同一函数值.一般而言,不同的key的hash值是不同的.在往hash表中映射的时候,不同的hash值可能映射到同一存储地址,这种情况被称为冲突. 解决冲突的方法: 1. 链表法:将冲突的各个元素用一个一维数组来维护.(java源码实现) 2. 开发寻址法:具体的有线性探测法.二次

java集合框架之java HashMap代码解析

 java集合框架之java HashMap代码解析 文章Java集合框架综述后,具体集合类的代码,首先以既熟悉又陌生的HashMap开始. 源自http://www.codeceo.com/article/java-hashmap-java-collection.html 签名(signature) public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Se

Java集合框架之HashMap

HashMap 的底层由一个散列表来实现,存储的内容是键值对(key-value),且键值不能重复,最多允许有一个null值. 1.Map与Set的关系 Set集合的特点是不能存储重复元素,不能保持元素插入时的顺序,且key值最多允许有一个null值. 由于Map中的key与Set集合特点相同,所以如果将Map中的value值当作key的附属的话,所有的key值就可以组成一个Set集合. 两者的实现类图也比较相似,见Java集合框架之基础. 2.Map接口中定义的方法 Map接口中定义的部分重要

Java基础知识强化之集合框架笔记57:Map集合之HashMap集合(HashMap&lt;Student,String&gt;)的案例

1. HashMap集合(HashMap<Student,String>)的案例 HashMap<Student,String>键:Student      要求:如果两个对象的成员变量值都相同,则为同一个对象.值:String HashMap是最常用的Map集合,它的键值对在存储时要根据键的哈希码来确定值放在哪里. HashMap 中作为键的对象必须重写Object的hashCode()方法和equals()方法 2. 代码示例: (1)Student.java,如下: 1 pa

集合框架学习笔记

集合框架由来 Java2之前,Java是没有完整的集合框架的.它只有一些简单的可以自扩容的容器类,比如 Vector,Stack,Hashtable等 为什么存在容器(可以存储多个数据) 数组的弊端: 1,长度是不可变的,一旦数组初始化之后,长度是固定的 2,在N个地方需要存储多个数据,都得专门写数组的操作方法,代码和功能重复 3,数组定义方法参差不齐集合框架:是为表示和操作集合而规定的一种统一的标准的体系结构.任何集合框架都包含三大块内容:对外的接口,接口的实现和对集合运算的算法为什么需要集合

Java修炼之道--集合框架

原作地址:https://github.com/frank-lam/2019_campus_apply 前言 Java集合框架 (Java Collections Framework, JCF) 也称容器,这里可以类比 C++ 中的 STL,在市面上似乎还没能找到一本详细介绍的书籍.在这里主要对如下部分进行源码分析,及在面试中常见的问题. 例如,在阿里面试常问到的 HashMap 和 ConcurrentHashMap 原理等等.深入源码分析是面试中必备的技能,通过本文的阅读会对集合框架有更深一