阅读源码是和大师面对面交流的机会之ArrayList检查是否有重复元素

来源:互联网 发布:js form submit 编辑:程序博客网 时间:2024/06/06 02:14
    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;    }
@Testpublic class Test {        ArrayList<User> userList= new ArrayList<User>();        User user1 = new User(1,"小明");        User user2 = new User(1,"小明");        userList.add(user1);        //userList.add(user2);        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) {//判断obj是否是User的一个实例            User u = (User) obj;   //强制转换            return this.id==u.id&&this.name.equals(u.name);   //直接比较属性值        }else{            return false;        }    }
    这样的equals方法对于对象的比较才有实际意义,当我们在采用ArrayList装载对象时,可以采用这种方式来判断是否有重复对象。