Java中提供了删除List最后一个元素的方法,常用的是remove(int index)和remove(Object obj),它们可以移除List中指定位置或对象的元素。在实际开发中,删除最后一个元素是非常常见的操作,例如在购物车中删除最后一个商品、栈中弹出最后一个元素等等。
当remove中的对象是int类型的时候默认remove(int index),
因此remove(2)和remove((Object)2) 不一样;前者是删除index后者是删除一个的2;
remove index只需要删除位置元素,然后其他的往前移动;0(n)复杂度
remove Object需要遍历数组的每一个,然后其他的往前移动,删除一个就返回;0(n2)复杂度,
1.使用for循环的时候
List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); list.add(5); list.add(6); for (int i = 0; i < list.size(); i++) { if(list.get(i)==4||list.get(i)==5){ list.remove(i);//删除index } }
[1, 2, 3, 5, 6],可以看出来在删除第一个4后,第二个5被删除了,但是第一个5并没有;
for (int i = 0; i < list.size(); i++) { if(list.get(i)==5){ list.remove((Object)(5)); } }
[1, 2, 3, 4, 5, 5, 6]
[1, 2, 3, 4, 5, 6]也是如此;
原因是,index位置删除后,所有元素会左移动,因此,移动后原位置元素会漏判;
2.使用for each
for (int i :list) { if(i==5){ list.remove((Object)(5)); } }
直接报错,Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
通过代码我们发现 Itr 是 ArrayList 中定义的一个私有内部类,在 next、remove方法中都会调用checkForComodification 方法,该方法的 作用是判断 modCount != expectedModCount
是否相等,如果不相等则抛出ConcurrentModificationException
异常。
解决办法:
1.倒序遍历
for(int i=list.size()-1;i>=0;i--){ if(list.get(i)==4||list.get(i)==5){ list.remove(i); } } [1, 2, 3, 4, 5, 5, 6] [1, 2, 3, 6]
原理:
倒序删除的时候,留在原位的元素是已经判断过的不满足条件的元素,所以正确;
2.迭代器删除
Iterator<Integer> it=list.iterator(); while(it.hasNext()){ if(it.next()==5){ it.remove(); } }
原理: ArrayList.this.remove(lastRet); cursor = lastRet;当前位置在删除后 又重新进行了判断;相当于index--;
本质上还是调用的remove(index)方法
3.removeif(i->i==5);
list.removeIf(i->i==5); System.out.println(list);
原理:
本质上调用的是迭代器方法
default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }
总结:
1、用for循环遍历List删除元素时,需要注意索引会左移的问题。
2、List删除元素时,为避免陷阱,建议使用迭代器iterator的remove方式、倒序或者removeif。
3、List删除元素时,默认按索引删除,而不是对象删除。