如何使用Java List等集合类的removeAll方法

实体类(User):

public class User {  
      
    private String name;  
    private int age;  
      
    //setter and getter  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public int getAge() {  
        return age;  
    }  
    public void setAge(int age) {  
        this.age = age;  
    }  
      
}

测试集合类(UserList):

import java.util.ArrayList;  
import java.util.List;  
  
public class UserList {  
      
    private List<User> subList;  
    private List<User> allList;  
      
    public UserList(){  
        subList=new ArrayList<User>();  
        allList=new ArrayList<User>();  
          
        for(int i=0;i<3;i++){  
            User user=new User();  
            user.setAge(i);  
            user.setName("lyh"+i);  
            subList.add(user);  
        }  
          
        for(int i=0;i<10;i++){  
            User user=new User();  
            user.setAge(i);  
            user.setName("lyh"+i);  
            allList.add(user);  
        }  
    }  
      
    public static void main(String[] args){  
        UserList userList=new UserList();  
        userList.allList.removeAll(userList.subList);//调用removeAll方法  
          
        System.out.println(userList.allList.size());  
          
    }  
}

诸君认为最后的打印的结果是多少? 7 ? That's wrong !! 结果是10

为什么会这样哪?难道removeAll方法有问题?

原因解析,先看API

boolean removeAll(Collection<?> c)

  从列表中移除指定 collection 中包含的其所有元素(可选操作)。   

没错,就是移除子集合包含的元素,那为什么不是7,而是10

再看API说明,移除所包含的其所有元素,注意这个字眼:包含

因为在执行removeAll方法时,会先对集合元素进行比较,如果元素相等才执行移除操作,说到这,相信很多人都已经明白是怎么回事了,因为不相等(equals),所以没有执行移除。 

查看源码进一步证实上述猜测,remove和removeAll的方法实现在:

java.util.AbstractCollection<E>

具体代码为:

public boolean removeAll(Collection<?> c) {  
       boolean modified = false;  
       Iterator<?> it = iterator();  
       while (it.hasNext()) {  
           if (c.contains(it.next())) {  
               it.remove();  
               modified = true;  
           }  
       }  
       return modified;  
}
public boolean remove(Object o) {  
        Iterator<E> it = iterator();  
        if (o==null) {  
            while (it.hasNext()) {  
                if (it.next()==null) {  
                    it.remove();  
                    return true;  
                }  
            }  
        } else {  
            while (it.hasNext()) {  
                if (o.equals(it.next())) {  
                    it.remove();  
                    return true;  
                }  
            }  
        }  
        return false;  
}

可以看到在调用removeAll方法时,实际上是循环调用了remove方法,而remove方法中有一段关键的代码:if (o.equals(it.next()))

So,得出结论,因为上述例子中的实体类没有Override hashCode和equals方法 !而在执行removeAll方法时是通过equals方法来判断集合元素是否相等的,如果没有Override equals方法,其默认的仍是比较对象,所以会出现上述问题!

问题综述完毕,这个问题实质上很简单,只希望给遇到有同样疑问的朋友一点帮助。


未经允许请勿转载:程序喵 » 如何使用Java List等集合类的removeAll方法

点  赞 (0) 打  赏
分享到: