在Java語言中,一般不需要自定義equals()和hashCode()這兩個方法,當需要對對象的內容進行比較的時候,才需要這樣兩個方法。例如,需要把對象放入HashSet或者把對象作爲key放入HashMap、 Hashtable時,如果不想把具有相同內容的兩個對象作爲兩個對象來看待,就需要重定義這兩個方法。這兩個方法的使用是緊密配合的,要是設計了其中一個,就要設計另外一個。
- 對稱性:如果x.equals(y)返回是“true”,那麼y.equals(x)也應該返回是“true”。
- 反射性:x.equals(x)必須返回是“true”。
- 類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那麼z.equals(x)也應該返回是“true”。
- 一致性:如果x.equals(y)返回是“true”,只要x和y內容一直不變,不管你重複x.equals(y)多少次,返回都是“true”。
- 如果x.equals(y)返回“true”,那麼x和y的hashCode()必須相等。
- 如果x.equals(y)返回“false”,那麼x和y的hashCode()有可能相等,也有可能不等。
import java.util.HashMap;
import java.util.Map;
/**
* 測試equals()、hashCode()方法對對象在Collection中的影響。
*
*/
public class EqualsAndHashCode
{
/**
* @param args
*/
public static void main(String[] args)
{
Point p1 = new Point(1,2);
Point p2 = new Point(1,2);
System.out.println("p1.equals(p2):" + p1.equals(p2));
System.out.println("p1.hashCode():" + p1.hashCode());
System.out.println("p2.hashCode():" + p2.hashCode());
Map<Point, String> map1 = new HashMap<Point, String>();
map1.put(p1, "point 1");
map1.put(p2, "point 2");
System.out.println("map1.size():" + map1.size());
BadPoint bp1 = new BadPoint(1,2);
BadPoint bp2 = new BadPoint(1,2);
System.out.println("bp1.equals(bp2):" + bp1.equals(bp2));
System.out.println("bp1.hashCode():" + bp1.hashCode());
System.out.println("bp2.hashCode():" + bp2.hashCode());
Map<BadPoint, String> map2 = new HashMap<BadPoint, String>();
map2.put(bp1, "point 1");
map2.put(bp2, "point 2");
System.out.println("map2.size():" + map2.size());
GoodPoint gp1 = new GoodPoint(1,2);
GoodPoint gp2 = new GoodPoint(1,2);
System.out.println("gp1.equals(gp2):" + gp1.equals(gp2));
System.out.println("gp1.hashCode():" + gp1.hashCode());
System.out.println("gp2.hashCode():" + gp2.hashCode());
Map<GoodPoint, String> map3 = new HashMap<GoodPoint, String>();
map3.put(gp1, "point 1");
map3.put(gp2, "point 2");
System.out.println("map3.size():" + map3.size());
}
}
/**
* 沒有重載equals()、hashCode()方法。
*/
class Point
{
private int x;
private int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
}
/**
* 重載了equals()方法,導致equals()返回true,而hashCode不同。
* 這是一個不好的設計(甚至是錯誤的)。
*/
class BadPoint
{
private int x;
private int y;
public BadPoint(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
@Override
public boolean equals(Object obj)
{
if (obj == null) return false;
if (!(obj instanceof BadPoint)) return false;
BadPoint objPoint = (BadPoint) obj;
if (this.x == objPoint.x && this.y == objPoint.y) return true;
return false;
}
}
/**
* 重載了equals()、hashCode()方法。
*/
class GoodPoint
{
private int x;
private int y;
public GoodPoint(int x, int y)
{
this.x = x;
this.y = y;
}
public int getX()
{
return this.x;
}
public int getY()
{
return this.y;
}
@Override
public boolean equals(Object obj)
{
if (obj == null) return false;
if (!(obj instanceof GoodPoint)) return false;
GoodPoint objPoint = (GoodPoint) obj;
if (this.x == objPoint.x && this.y == objPoint.y) return true;
return false;
}
@Override
public int hashCode()
{
int result = 17;
result = 31 * result + this.x;
result = 31 * result + this.y;
return result;
}
}