List是允许存在重复元素的,同样ArrayList也允许。那么ArrayList是如何检测是否存在重复元素的?下面我们浅读一下源码:
/**
* 判断列表是否包含某对象
* @param o
* @return
*/
public boolean contains (Object o){
return indexOf(o)>=0 ;
}
contains()方法会返回是boolean,会告诉你是否存在该元素。元素是否重复的具体判断方法是indexOf():
/**
* 判断对象是否存在与某个列表中
* 大多数情况下不能满足需求,实体对象的比较往往需要重写equals方法去直接比较对象的属性
* @return
*/
public int indexOf (Object objec){
if (objec == null ){
for (int i=0 ;i<size;i++){
if (elementData[i]==null ){
return i;
}
}
}else {
for (int i=0 ;i<size;i++){
if (objec.equals(elementData[i]))
return i;
}
}
return -1 ;
}
在源码中可以看出,indexOf对null对象也会进行比较,非空对象则会调用所有对象都具有的方法:equals()进行是否重复的比较。
但是有个问题,就是equals()方法对一些基本类型的比较可以返回较为真的值,但是对于一些entity对象就不行了,比如下面的这例子:
public class User{
private int id;
private String name;
}
@Test
public class Test {
ArrayList<User> userList= new ArrayList<User>();
User user1 = new User(1 ,"小明" );
User user2 = new User(1 ,"小明" );
userList.add(user1);
System.out .println(userList.contains(user2));
}
输出是false,但是在实际的业务逻辑中,此处应该返回的是true,因为我们用new在内存中开辟了两个对象空间,而对象自带的equals方法会对对象的引用地址进行比较,所以得出了两个对象虽然属性相等但却不重复的结果,这时候就需要我们重写对象的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 ;
}
}
这样的equals方法对于对象的比较才有实际意义,当我们在采用ArrayList装载对象时,可以采用这种方式来判断是否有重复对象。