根据“类是否覆盖equals()方法”,将它分为2类。
若某个类没有覆盖equals()方法,当它的通过equals()比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象。
我们可以覆盖类的equals()方法,来让equals()通过其它方式比较两个对象是否相等。通常的做法是:若两个对象的内容相等,则equals()方法返回true;否则,返回fasle。
“hashCode() 和 equals() ”是有关系的:
1)、如果两个对象相等,那么它们的hashCode()值一定相同。
这里的相等是指,通过equals()比较两个对象时返回true。
2)、如果两个对象hashCode()相等,它们并不一定相等。
因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等
参考代码 (ConflictHashCodeTest1.java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| 1 import java.util.*; 2 import java.lang.Comparable; 3 4
10 public class ConflictHashCodeTest1{ 11 12 public static void main(String[] args) { 13 14 Person p1 = new Person("eee", 100); 15 Person p2 = new Person("eee", 100); 16 Person p3 = new Person("aaa", 200); 17 18 19 HashSet set = new HashSet(); 20 set.add(p1); 21 set.add(p2); 22 set.add(p3); 23 24 25 System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode()); 26 27 System.out.printf("set:%s\n", set); 28 } 29 30
33 private static class Person { 34 int age; 35 String name; 36 37 public Person(String name, int age) { 38 this.name = name; 39 this.age = age; 40 } 41 42 public String toString() { 43 return "("+name + ", " +age+")"; 44 } 45 46
49 @Override 50 public boolean equals(Object obj){ 51 if(obj == null){ 52 return false; 53 } 54 55 56 if(this == obj){ 57 return true; 58 } 59 60 61 if(this.getClass() != obj.getClass()){ 62 return false; 63 } 64 65 Person person = (Person)obj; 66 return name.equals(person.name) && age==person.age; 67 } 68 } 69 }
|
运行结果:
p1.equals(p2) : true; p1(1169863946) p2(1690552137) set:[(eee, 100),
(eee, 100), (aaa, 200)]
结果分析:
我们重写了Person的equals()。但是,很奇怪的发现:HashSet中仍然有重复元素:p1
和 p2。为什么会出现这种情况呢?
这是因为虽然p1 和
p2的内容相等,但是它们的hashCode()不等;所以,HashSet在添加p1和p2的时候,认为它们不相等。
下面,我们同时覆盖equals() 和 hashCode()方法。
参考代码 (ConflictHashCodeTest2.java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| 1 import java.util.*; 2 import java.lang.Comparable; 3 4
10 public class ConflictHashCodeTest2{ 11 12 public static void main(String[] args) { 13 14 Person p1 = new Person("eee", 100); 15 Person p2 = new Person("eee", 100); 16 Person p3 = new Person("aaa", 200); 17 Person p4 = new Person("EEE", 100); 18 19 20 HashSet set = new HashSet(); 21 set.add(p1); 22 set.add(p2); 23 set.add(p3); 24 25 26 System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode()); 27 28 System.out.printf("p1.equals(p4) : %s; p1(%d) p4(%d)\n", p1.equals(p4), p1.hashCode(), p4.hashCode()); 29 30 System.out.printf("set:%s\n", set); 31 } 32 33
36 private static class Person { 37 int age; 38 String name; 39 40 public Person(String name, int age) { 41 this.name = name; 42 this.age = age; 43 } 44 45 public String toString() { 46 return name + " - " +age; 47 } 48 49
52 @Override 53 public int hashCode(){ 54 int nameHash = name.toUpperCase().hashCode(); 55 return nameHash ^ age; 56 } 57 58
61 @Override 62 public boolean equals(Object obj){ 63 if(obj == null){ 64 return false; 65 } 66 67 68 if(this == obj){ 69 return true; 70 } 71 72 73 if(this.getClass() != obj.getClass()){ 74 return false; 75 } 76 77 Person person = (Person)obj; 78 return name.equals(person.name) && age==person.age; 79 } 80 } 81 }
|
运行结果:
p1.equals(p2) : true; p1(68545) p2(68545) p1.equals(p4) : false;
p1(68545) p4(68545) set:[aaa - 200, eee - 100]
结果分析:
这下,equals()生效了,HashSet中没有重复元素。
比较p1和p2,我们发现:它们的hashCode()相等,通过equals()比较它们也返回true。所以,p1和p2被视为相等。
比较p1和p4,我们发现:虽然它们的hashCode()相等;但是,通过equals()比较它们返回false。所以,p1和p4被视为不相等。