如何使用Java List等集合类的removeAll方法
2011-06-07 09:35
429 查看
看到这个标题,估计很多人会纳闷:连集合类的removeAll方法都用不好还当什么程序员。
好吧,我承认我确实没用好这个方法,鄙视我吧。O(∩_∩)O哈!
先贴问题--->
实体类(User):
诸君认为最后的打印的结果是多少? 7 ?That's wrong !! 结果是10。
为什么会这样哪?难道removeAll方法有问题?
这个就是最近在用到removeAll时遇到的疑问(当然,我是把实际中的问题简单的抽象出来了)。当时百思不得其解,甚至幼稚的以为是Java的BUG 。殊不知是自己脑袋BUG了 !
原因解析:
先看API
boolean removeAll(Collection<?> c)
从列表中移除指定 collection 中包含的其所有元素(可选操作)。
没错,就是移除子集合包含的元素,那为什么不是7,而是10 。
再看API说明,移除所包含的其所有元素,注意这个字眼:包含!
因为在执行removeAll方法时,会先对集合元素进行比较,如果元素相等才执行移除操作,说到这,相信很多人都已经明白是怎么回事了,因为不相等(equals),所以没有执行移除。
查看源码进一步证实上述猜测,remove和removeAll的方法实现在:
具体代码为:
可以看到在调用removeAll方法时,实际上是循环调用了remove方法,而remove方法中有一段关键的代码:if (o.equals(it.next())) !
So,得出结论,因为上述例子中的实体类没有Override hashCode和equals方法 !而在执行removeAll方法时是通过equals方法来判断集合元素是否相等的,如果没有Override equals方法,其默认的仍是比较对象,所以会出现上述问题!
归根到底,还是基础没有掌握牢固,同时也给自己提了个醒,写实体类时尽量Override hashCode和equals方法,不这样说不定哪天就会出问题。
问题综述完毕,当然,这个问题实质上很简单,只希望给遇到有同样疑问的朋友一点帮助。
好吧,我承认我确实没用好这个方法,鄙视我吧。O(∩_∩)O哈!
先贴问题--->
实体类(User):
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方法有问题?
这个就是最近在用到removeAll时遇到的疑问(当然,我是把实际中的问题简单的抽象出来了)。当时百思不得其解,甚至幼稚的以为是Java的BUG 。殊不知是自己脑袋BUG了 !
原因解析:
先看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方法,其默认的仍是比较对象,所以会出现上述问题!
归根到底,还是基础没有掌握牢固,同时也给自己提了个醒,写实体类时尽量Override hashCode和equals方法,不这样说不定哪天就会出问题。
问题综述完毕,当然,这个问题实质上很简单,只希望给遇到有同样疑问的朋友一点帮助。
相关文章推荐
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- 如何使用Java List等集合类的removeAll方法
- Java List等集合类的removeAll方法
- 源程序List1.java,展示了如何使用list()方法来检查一个目录的内容的实例
- 【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法
- 如何在Android平台上使用JS直接调用Java方法
- 牛客网Java刷题知识点之什么是内部类、为什么要使用内部类、内部类如何使用外部类的属性和方法、成员内部类、局部内部类、静态内部类、匿名内部类
- java LinkedList的使用方法介绍
- 有关如何在java代码中使用json来互转对象、List、Map等
- java之io之File类的list()方法过滤目录的使用
- 【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法
- Java中List的使用方法简单介绍
- 【cocos2d-js官方文档】二十四、如何在android平台上使用js直接调用Java方法
- Java-List泛型的用处(能够使用传入泛型对象的方法)
- 如何使用java反射技术调用类和方法及给方法传参