最近咋使用 list.remove 方法的时候出了点问题。。。
贴出来,记录下。
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Integer> list = new ArrayList();// =null error
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
list.add(8);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) > 4)
list.remove(i);
}
System.out.println(Arrays.toString(list.toArray()));
}
假定我们的代码如上。就是想把list里面大于4的值都remove掉,然后得到的list。
可是这个程序在运行后,会按照预期的值,打印出来的结果都是小于4的吗???
打印结果为:[1, 2, 3, 4, 6, 8]
答案是否定。主要是使用 i 下标在 list 内索引时,由于使用了remove会导致list内部的数组总值也就是length
变小,从而导致使用i在数组内索引时会导致空过一个元素。
解决办法有两个:
第一个将i从list.size()-1 开始索引,从后向前遍历就不会出问题的。
还有就是使用 迭代 Iterator 。
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() > 4) {
it.remove();
}
}
这个可以主要是ArrayList内部的iterator返回的Iterator对象的remove方法在remove过之后会将当前索引值 减一。
相关内部实现为:
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch(IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
从而可以成功的达到我们的目的。