关于List.remove在for循环中出现问题的解决方案

在java中对list进行操作很频繁,特别是进行list启遍历,这些操作我们都会,也很熟悉,但是对java中list进行删除元素,remove list中的元素就不怎么熟悉了吧,可以说很陌生,是实际操作中也很容易出错,先看看下面这个java中如何remove list 中的元素吧.


  1. public class test {
  2. public static void main(String[] args) {
  3. String str1 = new String("abcde");
  4. String str2 = new String("abcde");
  5. String str3 = new String("abcde");
  6. String str4 = new String("abcde");
  7. String str5 = new String("abcde");
  8. List list = new ArrayList();

  9. list.add(str1);
  10. list.add(str2);
  11. list.add(str3);
  12. list.add(str4);
  13. list.add(str5);

  14. System.out.println("list.size()=" + list.size());
  15. for (int i = 0; i < list.size(); i++) {
  16. if (((String) list.get(i)).startsWith("abcde")) {
  17. list.remove(i);
  18. }
  19. }
  20. System.out.println("after remove:list.size()=" + list.size());
  21. }
  22. }

大家觉得这个程序打印出来的结果是多少呢?

Java代码
  1. 运行结果不是:

  2. list.size()=5

  3. after remove:list.size()=0

而是:

Java代码
  1. list.size()=5

  2. after remove:list.size()=2

这是怎么回事呢?到底要如何remove list 中的元素呢?

原因:List每remove掉一个元素以后,后面的元素都会向前移动,此时如果执行i=i+1,则刚刚移过来的元素没有被读取。


怎么解决?有三种方法可以解决这个问题:

1.倒过来遍历list

Java代码
  1. for (int i = list.size()-1; i > =0; i--) {
  2.   if (((String) list.get(i)).startsWith("abcde")) {
  3.    list.remove(i);
  4.   }
  5. }

2.每移除一个元素以后再把i移回来

Java代码
  1. for (int i = 0; i < list.size(); i++) {
  2.   if (((String) list.get(i)).startsWith("abcde")) {
  3.    list.remove(i);
  4.    i=i-1;
  5.   }
  6. }
3.使用iterator.remove()方法删除
Java代码
if (null != list && list.size() > 0) {
    Iterator it = list.iterator();  
    while(it.hasNext()){
        Student stu = (Student)it.next(); 
        if (stu.getStudentId() == studentId) {
            it.remove(); //移除该对象
        }
    }
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
循环使用 `lockFailBillList.removeAll(batch)` 可能会导致 `ConcurrentModificationException` 异常。这是因为在遍历 `lockFailBillList` 的同时,我们试图修改它。 为了避免此问题,一种解决方案是在循环结束后创建一个新的列表,将成功锁定的账单从原始列表移除,并返回新列表。以下是修改后的代码示例: ```java private List<Bill> retryLockingBills(List<Bill> bills, String projectId, PropertyUser propertyUser) { int[] BATCH_SIZES = {100, 50, 10, 1}; List<Bill> lockFailBillList = new ArrayList<>(bills); List<Bill> successfullyLockedBills = new ArrayList<>(); for (int batchSize : BATCH_SIZES) { List<List<Bill>> batchBillList = Lists.partition(lockFailBillList, batchSize); for (List<Bill> batch : batchBillList) { try { billTagApplyService.lockOrUnlockBill(batch, projectId, true, LockTypeEnum.LOCK_TYPE_ENUM_16.getCode(), propertyUser, true); successfullyLockedBills.addAll(batch); // 将成功锁定的账单添加到新列表 } catch (Exception e) { // 锁定失败继续执行下一批 } } lockFailBillList.removeAll(successfullyLockedBills); // 从原始列表移除成功锁定的账单 successfullyLockedBills.clear(); // 清空成功锁定的账单列表 } return lockFailBillList; } ``` 在上述修改,我们创建了一个新的列表 `successfullyLockedBills`,用于保存成功锁定的账单。在每个批次大小的循环,如果账单成功锁定,我们将其添加到 `successfullyLockedBills` 列表。在每个批次大小循环结束后,我们使用 `lockFailBillList.removeAll(successfullyLockedBills)` 语句从原始列表移除成功锁定的账单,然后清空 `successfullyLockedBills` 列表。 这样做可以避免在循环修改正在遍历的列表,从而避免 `ConcurrentModificationException` 异常。 希望这次的解答对你有帮助!如果你还有其他问题,请随时提问。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值