技术问答-17

compareComparables:

identityHashCode : https://www.cnblogs.com/godtrue/p/6341473.html
https://blog.csdn.net/qsdnmd/article/details/82914460

 /**
     * Returns k.compareTo(x) if x matches kc (k's screened comparable
     * class), else 0.
         * 比较k 与 x  如果x为空 或者 x类不是kc(kc是上一步获取的继承Comparable的添加泛型的变量) 返回0 
         *  否则返回k.compareTo(x)
     */@SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparablestatic int compareComparables(Class<?> kc, Object k, Object x) {return (x == null || x.getClass() != kc ? 0 :((Comparable)k).compareTo(x));}

/**
 * 一个对象的hashCode和identityHashCode 的关系:
 * 1:对象的hashCode,一般是通过将该对象的内部地址转换成一个整数来实现的
 * 2:当一个类没有重写Object类的hashCode()方法时,它的hashCode和identityHashCode是一致的
 * 3:当一个类重写了Object类的hashCode()方法时,它的hashCode则有重写的实现逻辑决定,此时的hashCode值一般就不再和对象本身的内部地址有相应的哈希关系了
 * 4:当null调用hashCode方法时,会抛出空指针异常,但是调用System.identityHashCode(null)方法时能正常的返回0这个值
 * 5:一个对象的identityHashCode能够始终和该对象的内部地址有一个相对应的关系,从这个角度来讲,它可以用于代表对象的引用地址,所以,在理解==这个操作运算符的时候是比较有用的
 *
 */

	 /**
	  * 比较a和b 要么返回-1 要么返回1   反正就是不能相等
     */static int tieBreakOrder(Object a, Object b) {int d;if (a == null || b == null ||(d = a.getClass().getName(). compareTo(b.getClass().getName())) == 0)d = (System.identityHashCode(a) <= System.identityHashCode(b) ? -1 : 1);return d;}

/**
	 * 把红黑树的根节点设为  其所在的数组槽 的第一个元素
	 * 首先明确:TreeNode既是一个红黑树结构,也是一个双链表结构
	 * 这个方法里做的事情,就是保证树的根节点一定也要成为链表的首节点
	 */static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) {int n;if (root != null && tab != null && (n = tab.length) > 0) { // 根节点不为空 并且 HashMap的元素数组不为空int index = (n - 1) & root.hash; // 取得根节点在数组中的位置  TreeNode<K,V> first = (TreeNode<K,V>)tab[index]; // 首先取得该位置上的第一个节点对象if (root != first) { // 如果root不是链表上的第一对象 //定义一个变量 	Node<K,V> rn;// 把元素数组index位置的元素替换为根节点对象 tab[index] = root;   
	           // 获取根节点对象的前一个节点TreeNode<K,V> rp = root.prev; if ((rn = root.next) != null) // 如果后节点不为空 ((TreeNode<K,V>)rn).prev = rp; // root后节点的前节点  指向到 root的前节点,相当于把root从链表中摘除!!  // 如果root的前节点不为空if (rp != null) 
	                rp.next = rn; // root前节点的后节点 指向到 root的后节点,到这就说明这个链表就和root无关了 这和上一步是关联操作  就是为了把root找出    if (first != null) // 如果数组该位置上原来的元素不为空first.prev = root; // 这个原有的元素的 前节点 指向到 root,相当于root目前位于链表的首位
	            root.next = first; // 原来的第一个节点现在作为root的下一个节点,变成了第二个节点root.prev = null; // 首节点没有前节点}
	 /*
	         * 这一步是防御性的编程
	         * 校验TreeNode对象是否满足红黑树和双链表的特性
	         * 如果这个方法校验不通过:可能是因为用户编程失误,破坏了结构(例如:并发场景下);也可能是TreeNode的实现有问题(这个是理论上的以防万一);
	         */ assert checkInvariants(root); }}

  /**
         * 递归校验TreeNode对象是否满足红黑树和双链表的特性
         */static <K,V> boolean checkInvariants(TreeNode<K,V> t) {TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,tb = t.prev, tn = (TreeNode<K,V>)t.next;if (tb != null && tb.next != t)return false;if (tn != null && tn.prev != t)return false;if (tp != null && t != tp.left && t != tp.right)return false;if (tl != null && (tl.parent != t || tl.hash > t.hash))return false;if (tr != null && (tr.parent != t || tr.hash < t.hash))return false;if (t.red && tl != null && tl.red && tr != null && tr.red)return false;if (tl != null && !checkInvariants(tl))return false;if (tr != null && !checkInvariants(tr))return false;return true;}}
上一篇:set集合存对象的时候是如何判断是不是同一个对象,其中含有重写equals方法和hashcode方法 后续


下一篇:Java_collection Object超类 hashCode()与equals()区别