HashMap put返回Null的问题

今早一过来就遇到一个bug,result.setData数据没写入成功,具体代码如下:

result.setData(new HashMap<>().put("stepType",stepType));

debug后发现data中的数据是null;

查hashMap源码:
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

创建对象没啥问题,下一步查put的源码:
/**
 * Associates the specified value with the specified key in this map.
 * If the map previously contained a mapping for the key, the old
 * value is replaced.
 *
 * @param key key with which the specified value is to be associated
 * @param value value to be associated with the specified key
 * @return the previous value associated with key, or
 *         null if there was no mapping for key.
 *         (A null return can also indicate that the map
 *         previously associated null with key.)
 */
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
看作者的注释: the previous value associated with key, or null if there was no mapping for key;
返回的是插入的key对应的上一个value,如果没有这个key的话,返回的就是null。
so,我们的put方法,不是返回的HashMap对象


看到这能知道为什么我们new HashMap<>().put("stepType",stepType)返回的是null了。再看一下put的具体实现:
/**
 * 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[] tab; Node 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 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)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
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}
这是JDk1.8的源码,put方式已经改成的红黑树实现,具体实现方法可自行解析。我们这边关注return oldValue;可以看到返回的是前值。

所以具体到刚才的业务代码,我们可以做如下修改:
result.setData(new HashMap<>().put("stepType",stepType));
使用匿名内部类:
result.setData(new HashMap(){
    {
        put("stepType",stepType);
    }
});

搞定!

还是基本功的问题啊,虽然扒下源码,很快就能改完,但这种问题以后还是尽量避免出现吧~

你可能感兴趣的:(Java日常)