关于List,ArrayList中remove(object obj)方法不能删除对象问题及解决方法

先看下面代码,大家猜猜打印的结果是什么?为什么?

package shiyan;  

import java.util.ArrayList;  
import java.util.List;  

public class ListTest {  

    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        List<A> list = new ArrayList<A>();  
        A a1 = newA(1,"a1");  
        A a2 = newA(2,"a2");  
        A a3 = newA(3,"a3");  
        A a4 = newA(4,"a4");  
        A a5 = newA(5,"a5");  

        list.add(a1);  
        list.add(a2);  
        list.add(a3);  
        list.add(a4);  
        list.add(a5);  

        list.remove(a2);  

        System.out.println(list.size());  
    }  

}  

class A{  
    int id;  
    String name;  
    public A(int id,String name){  
        this.id = id;  
        this.name = name;  
    }  

    public boolean equals(Object obj) {  
        return false;  
    }  

}  

如果您的回答是:4,我想您就有必要看看本文了,因为正确答案是5

先贴上:ArrayList上的remove源码:

public boolean remove(Object o) {  
    if(o == null) {  
        for(int index = 0; index < size; index++)  
        if(elementData[index] == null) {  
            fastRemove(index);  
            return true;  
        }  
    }else{  
        for(int index = 0; index < size; index++)  
        if(o.equals(elementData[index])) {  
            fastRemove(index);  
            return true;  
        }  
    }  
    return false;  
}  

看源码可知,List在删除对象时,先判断这个对象是否在自己的队列中?而这种判断指的是是否equals

因此,List在删除对象时,如果使用删除对象方法,应该最好重写equals方法,否则最好使用删除下标的方法。

注:删除下标时一定要确保下标的类型是int类型,若是Integer类型,List会默认匹配remove(Object o)方法,而不是remove(int index)方法。

解决方法:

比如现在有一个 Person类:

public class Person {
    private Long id;

    private String name;

    public Person(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

重写Person对象的equals()方法和hashCode()方法:

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (!id.equals(person.id)) return false;
        return name.equals(person.name);

    }

    @Override
    public int hashCode() {
        int result = id.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }

下面对象去重的代码:

 Person p1 = new Person(1l, "jack");
        Person p2 = new Person(3l, "jack chou");
        Person p3 = new Person(2l, "tom");
        Person p4 = new Person(4l, "hanson");
        Person p5 = new Person(5l, "胶布虫");

        List<Person> persons = Arrays.asList(p1, p2, p3, p4, p5, p5, p1, p2, p2);

        List<Person> personList = new ArrayList<>();
        // 去重
        persons.stream().forEach(
                p -> {
                    if (!personList.contains(p)) {
                        personList.add(p);
                    }
                }
        );
        System.out.println(personList);

List 的contains()方法底层实现使用对象的equals方法去比较的,其实重写equals()就好,但重写了equals最好将hashCode也重写了。

可以参见:https://blog.csdn.net/xyr05288/article/details/53736378

https://blog.csdn.net/jiaobuchong/article/details/54412094

 

展开阅读全文

没有更多推荐了,返回首页