🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## Java专题二:相等与比较 [TOC] ### 2.1.运算符== 基本数据类型(byte、short、int、long、char、float、double、boolean):判断数值是否相等 引用数据类型(类的对象):判断对象的地址是否相等,一般通过new关键词创建的对象都是不相等的。 ### 2.2.equals方法 **equals方法是判断对象相等最常使用的方法。** 如: 在ArrayList中判断是否包含某元素contains方法: 1.判断是否待查找的对象是否为null,为null的话,进入第2步,否则进入第3步 2.遍历ArrayList的元素数组,查找是否数组中包含null,查找结束 3.遍历ArrayList的元素数组,调用每个元素的equals方法,判断是否相等 **说明:** 如果2个对象的equals方法相等,则它们的hashCode方法一定会要产生相同的整形值,所以在定义类重载equals时候最好重写hashCode方法。 **定义equals方法一般原则**: 1. 判断this对象与anObject对象是否相等(`this == anObject`) 2. 判断anObject对象是否为类或其子类对象(`anObject instanceof String`) 3. 比较类中属性是否相等   基本类型,直接使用==判断   集合数组类型,遍历集合数组使用相应equals方法判断   引用数据类型,使用相应equals方法判断 4. 重写equals方法是总要重写hashCode方法(Always override hashCode when you override equals) 如String类的equals方法:   ```java // java.lang.String#equals public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } ``` ### 2.3.hashCode方法 如: HashMap的Hash表结构中,使用哈希函数定位元素的位置就是通过元素的hash值,即(h = key.hashCode()) ^ (h >>> 16);因此如果2个对象的hashCode返回相同的值,意味着产生冲突或者是同一个元素(Key的equals方法相等) **定义hashCode方法一般原则**: 1. 定义int类型变量hashCode并赋值1(`int hashCode = 1;`) 2. 对于每个成员变量,进行如下计算hash code `c`(根据字段类型): boolean:  ` (f ? 1 : 0)` byte, char, short, int: `(int) f` long: `(int) (f ^ (f >>> 32))` float: `Float.floatToIntBits(f)` double: `Double.doubleToLongBits(f)` Object: `(obj==null ? 0 : obj.hashCode())` 3. 对每个字段进行如下操作: `hashCode = 31 * hashCode + c;` 4. 返回hashCode(`return hashCode;`) ```java //java.util.AbstractList#hashCode public int hashCode() { int hashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; } ``` ### 2.4.Comparable接口与Comparator接口 涉及数组或列表有序存储或排序问题,如TreeMap自动排序和Arrays.sort方法,public static <T> void sort(T[] a, Comparator<? super T> c),都需要比较大小。 ```java public interface Comparable<T> { public int compareTo(T o); } ``` ```java public interface Comparator<T> { int compare(T o1, T o2); } ``` 在使用TreeMap时会对插入键值对元素的Key进行排序,必须通过比较排序。而比较就要用到上面2个接口: **第1种** :在TreeMap构造方法`public TreeMap(Comparator<? super K> comparator)`直接指定一个比较器,操作元素时调用比较器的compare方法实现Key的大小比较; **第2种** :Key类实现Comparable接口,操作元素时调用Key的compare方法来实现大小的比较。 其它则如下面所示,会抛出异常。 ```java class A{ } public class TreeMapTest { public static void main(String[] args){ TreeMap map = new TreeMap<A, String>(); map.put(new A(), "null");; } } ``` **运行报异常:** Exception in thread "main" java.lang.ClassCastException: A cannot be cast to java.lang.Comparable