JDK8:HashMap源码解析:newNode方法、Node类

一、概述

在Map中存储的每一个键值对都是以一个Map.Entry<K,V>的实现对象存储的,Map.Entry是一个接口,不能实例化,所以Map的不同实现类,存储键值对的方式也会有所不同,只要这个键值对的类实现了Map.Entry接口即可。

在HashMap中键值对的存储方式有两种:

其中一种是我们比较熟知的链表存储结构,也就是以HashMap.Node<K,V>类的对象方式存储的, Node类是HashMap的一个静态内部类,实现了 Map.Entry<K,V>接口。在调用put方法创建一个新的键值对时,会调用newNode方法来创建Node对象。

二、方法解析

// 该方法很简单,只是调用了Node类的构造函数
Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
        return new Node<>(hash, key, value, next);
}

我们接下来看下Node类的代码

/**
* 该类只实现了 Map.Entry 接口,
* 所以该类只需要实现getKey、getValue、setValue三个方法即可
* 除此之外以什么样的方式来组织数据,就和接口无关了
*/
static class Node<K,V> implements Map.Entry<K,V> {
        final int hash; // hash值,不可变
        final K key; // 键,不可变
        V value; // 值
        Node<K,V> next; // 下一个节点
 
        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
 
        // 实现接口定义的方法,且该方法不可被重写
        public final K getKey()        { return key; }
        // 实现接口定义的方法,且该方法不可被重写
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }
 
        // 重写父类Object的hashCode方法,且该方法不可被自己的子类再重写
        // 返回:key的hashCode值和value的hashCode值进行异或运算结果
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }
 
        // 实现接口定义的方法,且该方法不可被重写
        // 设值,返回旧值
        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
 
        /*
         * 重写父类Object的equals方法,且该方法不可被自己的子类再重写
         * 判断相等的依据是,只要是Map.Entry的一个实例,并且键键、值值都相等就返回True
         */
        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
}

三、小贴士

在上一个小节中存在着Objects.equals、Objects.hashCode这种静态方法,其内部实现都特别简单。

以下是截取Objects类中这两个方法的实现。

public static int hashCode(Object o) {
        return o != null ? o.hashCode() : 0;
}
 
public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
}

最主要的帮助用户节省了空值判断指针相同判断。

发布了69 篇原创文章 · 获赞 52 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/xzj80927/article/details/101054972