1.1 问题 List删除某项的时候,一般可以使用list.remove()方法,这在不循环的时候是可行的。但当涉及到循环删除一个List中满足某条件的项的时候,使用普通遍历会出现删除不完全的问题,使用增强遍历会出现报错的情况,如下示例代码:
普通遍历删除: for(int i=0;i(<)pairList.size();i++){ PairPerson pp=pairList.get(i); if(pp.getCulmulatedTime()<30){ pairList.remove(i); } } //小于号加括号是因为mackdown语法不熟悉,不知道怎么写代码块 //删除会出现跳过多个满足条件的项导致山和醋不完全的问题
增强遍历删除: for(PairPerson pp:pairList){ if(pp.getCulmulatedTime()<30){ pairList.remove(i); } } //会报ConCurrentModificationException异常(网上有说第一元素的删除成功,第二个才报错)
1.2 处理方式 使用Iterator迭代循环并删除满足条件项,可以完美解决这个问题
for(Iterator iter=pairList.iterator();iter.hasNext();){ PairPerson pp2= (PairPerson) iter.next(); if(pp2.getCulmulatedTime()<30){ iter.remove(); } }
1.3 问题原因分析 使用普通遍历的方式当删除一个元素的时候,其后所有元素的索引都会有变化,以ArrayList为例,删除一个元素,其后所有元素的下标减一,这就会导致往后遍历的时候漏掉下标减一之后变成刚刚删除的那个元素下标的元素,即,删除下标为3的第四个元素,下标为4的第五个元素下标会减一变成3,循环继续的时候会漏掉这个元素; 使用增强遍历的时候,需要考虑到其底层的实现机制,具体可以去网上查,这里不做解释,其结果是在循环过程从List中删除非基本数据类型以后,继续循环List时会报ConcurrentModificationException 错误;
遍历删除重复项有多种方案可以选择,这里写出两种:
2.1 移植 基本思路是遍历一遍将所有的不重复项拷贝到另一个List list2中,将原list清空,再将list2中的元素添加到原list中;这样的做法很简单,但算法比较笨,所以在涉及到大量数据的情况下,效率不容乐观,具体的实现可以在网上找到很多,这里不再做示例;
2.2 使用双层两端循环
示例代码: for(int i=0;i(<)fourPairPersonList.size()-1;i++) { InteractionPersonNumber ipn0=fourPairPersonList.get(i); for(int j=fourPairPersonList.size()-1;j>i;j–){ InteractionPersonNumber ipn =fourPairPersonList.get(j); if(ipn.getPerson()==ipn0.getPerson()){ boolean identical=ipn0.getInteractionList().containsAll(ipn.getInteractionList()); if(identical){ if(ipn.getStartTime()==ipn0.getStartTime()&&ipn.getEndTime()==ipn0.getEndTime()){ fourPairPersonList.remove(j); } } } } } 注:这里代码里面的类名之所以比较复杂,是因为我直接把我的源码拷贝过来了,读者可以不用收到列表名称以及类名的影响,代之以A,B,C…因为mackdown自动排版的关系,所以代码看起来没有层次感,希望不要太受影响,理解其思想即可,重点在于for()括号中的i,j的设置。两端循环可以保证留下所有重复项里面的一个元素。
