Java集合深入学习 - HashMap源码解析-2查找数据(基于jdk1.8)

Java集合深入学习 - HashMap源码解析-1基础(基于jdk1.8)

Java集合深入学习 - HashMap源码解析-2查找数据(基于jdk1.8)

Java集合深入学习 - HashMap源码解析-3添加与扩容(基于jdk1.8)

Java集合深入学习 - HashMap源码解析-4删改与遍历(基于jdk1.8)

 

 

1.查找数据get

    /**
     * 根据key获取数据
     */
    public V get(Object key) {
        Node<K,V> e;
        //获取节点,若节点非空,获取其value值否则返回null
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

    /**
     * 获取节点信息
     * key	键值对的键
     * hash	键的hash值
     */
    final Node<K,V> getNode(int hash, Object key) {
    	//定义局部变量
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        //是否已有数据(table非空,table中对应hash计算后的位置有数据)
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {	//(n - 1) & hash  n是2的次方,n-1的低位全是1,所以: (n - 1) & hash  == hash%n    
            if (first.hash == hash && //判断头节点hash值是否与key的hash值相等
                ((k = first.key) == key || (key != null && key.equals(k))))	//比较是否相等,或者equals为true
                return first;	//满足条件,查找得就是当前节点
            if ((e = first.next) != null) {	//查找下一个节点
                if (first instanceof TreeNode)	//判断当前节点结构是否为红黑树节点
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);	//获取对应节点
                do {	//不是红黑树节点,则是单链表结构,遍历链表
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;	//遍历到符合条件的节点,返回节点
                } while ((e = e.next) != null);
            }
        }
        return null;	//未获取到对应节点 返回null
    }

        /**
         * 红黑树 查找对应节点
         */
        final TreeNode<K,V> getTreeNode(int h, Object k) {
        	//查找根节点  调用对应的find方法查找数据
            return ((parent != null) ? root() : this).find(h, k, null);
        }

        /**
         * 获取树的根节点
         */
        final TreeNode<K,V> root() {
            for (TreeNode<K,V> r = this, p;;) {//向上遍历获取根节点
                if ((p = r.parent) == null)
                    return r;
                r = p;
            }
        }

        /**
         * 查找红黑树的节点 (当前节点是查找树的根节点)
         * @param h	对应key的hash值
         * @param k	对应key对象
         * @param kc key的class
         * @return 查找到的节点
         */
        final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
            TreeNode<K,V> p = this;	//获取当前节点  
            do {
                int ph, dir; K pk;
                TreeNode<K,V> pl = p.left, pr = p.right, q;
                if ((ph = p.hash) > h)	//当前节点hash值大于待查找节点哈市值   说明待查找节点在当前节点的左子树上
                    p = pl;		//查找左子树
                else if (ph < h)	//当前节点hash值小于待查找节点哈市值   说明待查找节点在当前节点的右子树上
                    p = pr;		//查找右子树
                else if ((pk = p.key) == k || (k != null && k.equals(pk)))	//hash值相等  比较key是否相等或equals
                    return p;	//查找到数据  返回当前节点
                //hash值相等  但是key不相等并且equals方法返回false  即当前节点不是待查找节点
                else if (pl == null)	//当前节点的左子节点为null
                    p = pr;		//查找其右子树
                else if (pr == null)	//当前节点的右子节点为null
                    p = pl;		//查找其左子树
                else if ((kc != null ||			//kc不为null
                          (kc = comparableClassFor(k)) != null) &&	//key对象实现了Comparable接口
                         (dir = compareComparables(kc, k, pk)) != 0) //k.compareTo(pk)返回结果赋值给dir
                    p = (dir < 0) ? pl : pr;	//根据compareTo方法返回结果判断查找对应左子树还是右子树
                else if ((q = pr.find(h, k, kc)) != null)	//按compareTo方法查找对应数据
                    return q;	//查找到,返回查找结果
                else
                    p = pl; //查找其左子树
            } while (p != null);
            return null;	//未查询到结果
        }

    /**
     * 判断传入的Object对象x是否实现了Comparable接口 返回对应类得class
     */
    static Class<?> comparableClassFor(Object x) {
        if (x instanceof Comparable) {
            Class<?> c; Type[] ts, as; Type t; ParameterizedType p;
            if ((c = x.getClass()) == String.class) // 若传入x是String直接返回String.class
                return c;
            /*
             * getGenericInterfaces()方法返回的是该对象的运行时类型“直接实现”的接口
             * 	返回的一定是接口,必然是该类型自己实现的接口,继承过来的不算。
             */
            if ((ts = c.getGenericInterfaces()) != null) {	
                for (int i = 0; i < ts.length; ++i) {	//遍历直接接口
                    if (((t = ts[i]) instanceof ParameterizedType) &&	//Type是ParameterizedType
                        ((p = (ParameterizedType)t).getRawType() ==		//ParameterizedType得getRawType()是Comparable.class
                         Comparable.class) &&
                        (as = p.getActualTypeArguments()) != null &&	//此类型实际类型参数
                        as.length == 1 && as[0] == c) 					// 长度是1 其值为传入类的class
                        return c;
                }
            }
        }
        return null;
    }

    /**
     * 如果x的类型是kc,返回k.compareTo(x)的比较结果
     * 如果x为空,或者类型不是kc,返回0
     */
    @SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable
    static int compareComparables(Class<?> kc, Object k, Object x) {
        return (x == null || x.getClass() != kc ? 0 :
                ((Comparable)k).compareTo(x));
    }

2.查找数据getOrDefault

    /**
     * 根据key获取数据,若未查找到对应数据,返回defaultValue
     */
    @Override
    public V getOrDefault(Object key, V defaultValue) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
    }

本问链接,转载请标注https://blog.csdn.net/luo_mu_hpu/article/details/106193009

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值