我们知道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。