在使用java list集合执行遍历操作时,Java程序员经常会遇到问题。 如果发生了问题,该怎么解决呢,初学者也非常棘手吧。 现在让我们总结并详细分析一下遍历java list集合操作中的常见问题。
Java list集合遍历操作的常见问题
1、以下四种方法有什么问题吗? 为什么?
公共void remove1(阵列列表) {
for (integera :列表) {
if(a=10
list.remove(a );
}
}
}
公共void remove2(阵列列表) {
Iterator it=list.iterator (;
while(it.Hasnext ) ) ) )。
if (it.next (=10 ) ) ) ) )。
it.remove (;
}
}
}
公共void remove3(阵列列表) {
Iterator it=list.iterator (;
while(it.Hasnext ) ) ) )。
it.remove (;
}
}
公共void remove4(阵列列表) {
Iterator it=list.iterator (;
while(it.Hasnext ) ) ) )。
it.next (;
it.remove (;
it.remove (;
}
}
答:这个问题是儿科,答案如下。
remove1方法抛出concurrentmodificationexception异常。 这是迭代器的陷阱,在foreach直通编译后将其替换为迭代器来实现。 普通的for循环不会抛出此异常。 list.size方法一般不会更改,因此只需删除即可。 为了在迭代器内部维护索引位置的数据,要求容器在迭代过程中不能发生结构性变化(不计入添加、插入、删除或修改的数据)。 否则,这些索引位置数据将无效。 避免的方法是使用迭代器的remove方法。
remove2方法可以正常工作,没有错误。
remove3方法抛出IllegalStateException异常,因为在使用迭代器remove方法之前必须调用next方法。 next方法检测容器是否发生了结构性变化,并更新cursor和lastRet的值。 如果在不直接调用next的情况下调用remove,相关值将变得不准确。
remove4方法抛出IllegalStateException异常。 原因与remove3相同,调用remove后,lastRet的值将重置为-1,如果在不调用next的情况下设置lastRet,则再次直接调用remove会自然导致状态异常。
2、以下程序片段的remove方法想删除list列表中的所有' android ',请说说每个remove方法是否有问题。 为什么? 我该怎么解决?
ArrayList list=new ArrayList (;
list.add(Java );
list.add(Android );
list.add(Android );
list.add(c );
list.add(c );
list.add(c );
公共void remove1(阵列列表) {
for(inti=0; I
strings=list.get(I;
if(s.equals(Android ) ) )
list.remove(s );
}
}
}
公共void remove2(阵列列表) {
字符串列表(for ) {
if(s.equals(Android ) ) )
list.remove(s );
}
}
}
a )上面程序中的remove1和remove2方法的工作方式如下:
执行remove1方法后,没有删除第二个" android "字符串。 请注意,ArrayList的remove方法(在ArrayList中是具有相同名称和两个不同参数的remove方法)实现了核心代码。
公共空间内存(objecto ) {
if (o==空) {
……
} else {
//一般元素遵循这个分支
for(intindex=0; 索引大小; index )
if(o.equals(elementdata[index] ) )
快速移除(索引;
返回真;
}
}
返回假;
}
私有语音流(intindex ) {
模式计数;
int numMoved=size - index - 1;
if (数字移动0 ) )。
system.arraycopy(elementData,index 1,elementdata,index,
数字移动;
element data [-- size ]=空; //clear to let GC do its work
}
最后的删除操作将执行System.arraycopy方法,表明删除元素涉及移动数组元素。 因此,遍历第一个字符串“android”时,因为满足删除条件,所以从数组中删除该元素,并将下一个元素移动到当前位置。 也就是第二个字符串“android”。 导致下一个循环遍历的下一个字符串“android”未被遍历,无法删除。 此外,由于每次删除时size也会减少一个,因此实际上每次都会向前移动,从而增加了遍历后无法获取的元素。 解决方案是按相反顺序删除遍历,如下所示。 不要认为通过将for循环中的list.size )引用到外部前置变量并取值就可以删除它。 该方法相对高效,如下所示:
公共void remove1(阵列列表) {
for(intI=list.size ) (-1; i=0; I----) {
strings=list.get(I;
if(s.equals(Android ) ) )
list.remove(s );
}
}
}
这是因为反向遍历数组不会影响后续元素的遍历,即使发生元素删除也是如此。
remove2方法执行会报for-each有名的并发修正异常Java.util.concurrentmodificationexception。 必须确保容器在迭代过程中不会发生结构性更改。 不计入添加、插入、删除和修改数据。 否则,这些索引位置数据将保留在内部