• HashMap的put方法返回值问题


    API文档中的描述:

    先看一个例子

    Map<Character, Integer> map = new HashMap<Character, Integer>();
    System.out.println(map.put('a', 0)); // null
    System.out.println(map.put('a', 1)); // 0
    System.out.println(map.put('a', 2)); // 1
    System.out.println(map.put('b', 1)); // null
    System.out.println(map.put('b', 2)); // 1
    System.out.println(map.get('a')); //2

    可以看出:put方法的返回值为null或value;

    调用put方法时,如果已经存在一个相同的key, 则返回的是前一个key对应的value,同时该key的新value覆盖旧value;
    如果是新的一个key,则返回的是null;

    通过hashmap的源码可以看出:

    map中一个映射不能包含重复的键。每个键最多只能映射一个值。即相同的key在Map中只会有一个与之关联的value存在。
    put()方法实现:首先使用hash(key)得到key的hashcode(),hashmap根据获得的hashcode找到要插入的位置所在的链,在这个链里面放的都是hashcode相同的Entry键值对,
    在找到这个链之后,会通过equals()方法判断是否已经存在要插入的键值对,而这个equals比较的就是key。
    添加对应的key-value这样的键值对node时,如果原本已经存在相同的key,则直接改变对应的value,并返回旧的value;如果不存在相同的key,则插入,在插入链表时,如果链表长度为临界长度TREEIFY_THRESHOLD,再插入任何元素就要变成红黑树。

    public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);//put方法调用putVal方法
        }
    
        /**
         * Implements Map.put and related methods
         *
         * @param hash hash for key
         * @param key the key
         * @param value the value to put
         * @param onlyIfAbsent if true, don't change existing value
         * @param evict if false, the table is in creation mode.
         * @return previous value, or null if none
         */
        final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
            Node<K,V>[] tab; Node<K,V> p; int n, i;
            if ((tab = table) == null || (n = tab.length) == 0)
                n = (tab = resize()).length;
            if ((p = tab[i = (n - 1) & hash]) == null)
                tab[i] = newNode(hash, key, value, null);
            else {
                Node<K,V> e; K k;
                if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                    e = p;
                else if (p instanceof TreeNode)
                    e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
                else {
                    for (int binCount = 0; ; ++binCount) {
                        if ((e = p.next) == null) {
                            p.next = newNode(hash, key, value, null);
                            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                                treeifyBin(tab, hash);
                            break;
                        }
                        if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                            break;
                        p = e;
                    }
                }
                if (e != null) { // existing mapping for key  //key已经存在
                    V oldValue = e.value; //将已经存在的结点e的value值赋给oldValue
                    if (!onlyIfAbsent || oldValue == null)//当onlyIfAbsent为false或者oldValue为null时,进行覆盖操作
                        e.value = value;//覆盖原结点的value值,用新值替换旧值
                    afterNodeAccess(e);
                    return oldValue;//返回的是被覆盖的oldValue
                }
            }
            ++modCount;
            if (++size > threshold)
                resize();
            afterNodeInsertion(evict);
            return null;
        }

    在hashset中的add方法调用的就是hashmap的put方法,判断put方法的返回值是否等于空,来保证hashset的值不重复。

    private transient HashMap<E,Object> map;
    
    /**
         * Adds the specified element to this set if it is not already present.
         * More formally, adds the specified element <tt>e</tt> to this set if
         * this set contains no element <tt>e2</tt> such that
         * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
         * If this set already contains the element, the call leaves the set
         * unchanged and returns <tt>false</tt>.
         *
         * @param e element to be added to this set
         * @return <tt>true</tt> if this set did not already contain the specified
         * element
         */
        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
  • 相关阅读:
    Excel中substitute替换函数的使用方法
    如何在Excel中提取小数点后面的数字?
    提升单元测试体验的利器--Mockito使用总结
    SpringMVC项目读取不到外部CSS文件的解决办法及总结
    java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
    Spring-data-redis操作redis知识总结
    优雅高效的MyBatis-Plus工具快速入门使用
    Thrift入门初探(2)--thrift基础知识详解
    Thrift入门初探--thrift安装及java入门实例
    spring事件驱动模型--观察者模式在spring中的应用
  • 原文地址:https://www.cnblogs.com/zeroingToOne/p/8607681.html
Copyright © 2020-2023  润新知