我們知道ArrayList是允許重復的,有序的元素的集合,但當我們想用它來放入不同的元素時,contains()方法就派上用場了。
首先,我們來看下contains()方法的源代碼:
public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } public boolean equals(Object obj) { return (this == obj); }
可知,如果對象不為null的話,最終是調用的Object類的equals()方法,來比較兩個對象的引用是否相同,在大多數情況下是不能滿足我們的需求的。比如:
我們有一個User類:
public class User { int id; String name; /* * Getters and Setters */ ...... }
public class Test { public static void main(String[] args) { ArrayList<User> student = new ArrayList<User>(); User user1 = new User(1,"yueliming"); User user2 = new User(1,"yueliming"); student.add(user1); if(!student.contains(user2)){ student.add(user2); } System.out.println(student.size()); } }
如果我們不在User類中重寫equals()方法的話,雖然我們用contains方法進行了判斷,得到的鏈表的size仍舊為2,因為我們用new關鍵字創建兩次User對象,雖然它們代表同一個人,但是JVM虛擬機在堆中開辟了兩個存儲空間,user1和user2分別為指向這兩個對象的引用,add方法只是將引用賦給student[i],很明顯,user1和user2的值不同,鏈表也就把它們均加入到了其中。
為了解決上述問題,我們只需要在User類中重寫equals()方法,user1和user2就會被當做同一個對象處理,equals()代碼如下:
public boolean equals(Object obj) { if(this ==obj){//如果是引用同一個實例 return true; } if (obj!=null && obj instanceof User) { User u = (User) obj; return this.id==u.id&&this.name.equals(u.name); }else{ return false; } }
可以看到,如果對象不為null的話,現在調用的User類的equals()方法對象的屬性是否相同,兩個字段均相同時才返回true。