【java基础-实战3】list遍历时删除元素的方法

插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。
坚持不懈,越努力越幸运,大家一起学习鸭~~~

在实际的业务开发中,容器的遍历可以说是非常非常常见的场景了,遍历删除呢,用的机会也比较多,那么有哪几种删除元素的方法呢?你用对了吗~
本文循序渐进,先说几种容易出问题的方法,再引出几种比较可靠的方法~

首先,初始化一个数组,用于后面的事例演示:

List<Integer> list = new ArrayList<>(); 
for (int i = 1; i < 5; i++) {
    if(i==2) {
      //i==2时添加两次,用于后面的测试
      list.add(i); 
      list.add(i); 
    }else {
      list.add(i); 
    }
}

方法一:for-each循环删除(结果:抛出异常)

for (String id : list){
   if (id.contains(3)) {
      list.remove(id); 
    }
 }

运行上面的代码,抛出如下异常:
image.png
抛出异常的根本原因在于for-each是使用Iterator来实现遍历的,调用ArrayList.remove()方法会将modCount+1,而Iterator内部的expectedModCount确没有更新,这样在进行下次循环时调用Iterator.next()会对modCount和expectedModCount进行比较,不一致就会抛出ConcurrentModificationException异常。
当删除完元素后,进行下一次循环时,会调用下面源码中Itr.next()方法获取下一个元素,会调用checkForComodification()方法对ArrayList进行校验,判断在遍历ArrayList是否已经被修改,由于之前对modCount+1,而Iterator中的expectedModCount还是初始化时ArrayList.Itr对象时赋的值,所以会不相等,然后抛出ConcurrentModificationException异常。

方法二:普通for循环正序删除(结果:会漏掉对后一个元素的判断)

for (int i = 0; i < list.size(); i++) {
    if (2==equals(list.get(i) )) {//2是要删除的元素
        list.remove(i);
        //解决方案: 加一行代码i = i - 1; 删除元素后,下标减1
    }
    System.out.println("当前List是"+list.toString());
}
//原ArrayList是[1, 2, 3, 3, 4]
//删除后是[1, 2, 3, 4], 少删除了一个元素2

可以看到少删除了一个元素"2".

原因在于调用remove删除元素时,remove方法调用System.arraycopy()方法将后面的元素移动到前面的位置,也就是第二个num:2会移动到数组下标为2的位置,而在下一次循环时,i+1之后,i会为2,不会对数组下标为1这个位置进行判断,所以这种写法,在删除元素时,被删除元素a的后一个元素b会移动a的位置,而i已经加1,会忽略对元素b的判断,所以如果是连续的重复元素,会导致少删除。
**解决方案:**可以在删除元素后,执行i=i-1,使得下次循环时再次对该数组下标进行判断。

方法三:普通for循环倒序删除(结果:正确删除)

 for (int i = list.size() -1 ; i>=0; i--) {
    if (list.get(i).equals(2)) {
        list.remove(i);
    }
    System.out.println("当前list是"+list.toString());
}


//原ArrayList是[1, 2, 3, 3, 4]
//删除后是[1, 3, 4]

这种方法可以正确删除元素,因为调用remove删除元素时,remove方法调用System.arraycopy()将被删除元素a后面的元素向前移动,而不会影响元素a之前的元素,所以倒序遍历可以正常删除元素。

方法四:Iterator遍历,使用ArrayList.remove()删除元素(结果:抛出异常)

Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
    Integer value = iterator.next();
    if (value.equals(3)) {//3是要删除的元素
            list.remove(value);
    }
    System.out.println("当前list是"+list.toString());
}

第4种方法其实是第1种方法在编译后的代码,所以第四种写法也会抛出ConcurrentModificationException异常。这种需要注意的是,每次调用iterator的next()方法,会导致游标向右移动,从而达到遍历的目的。所以在单次循环中不能多次调用next()方法,不然会导致每次循环时跳过一些元素.

方法五: Iterator遍历,使用Iterator的remove删除元素(结果:正确删除)

Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
    Integer value = iterator.next();
    if (value.equals(3)) {//3是需要删除的元素
        iterator.remove();
    }
}

方法5可以正确删除元素。

跟第1种和第4种方法的区别在于是使用**iterator.remove();**来移除元素,而在remove()方法中会对iterator的expectedModCount变量进行更新,所以在下次循环调用iterator.next()方法时,expectedModCount与modCount相等,不会抛出异常。

方法六:jdk8+ 流方式 list.removeIf (结果:正确删除)

jdk8+ 推荐下面这种写法,简洁明了

list.removeIf(s -> s.contains(3));

结论:

在list遍历中不要使用list.remove(), 容易出问题;
推荐使用方法五的iterator.remove()或者方法六的 list.removeIf().

  • 17
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是Java读取Word表格的实战步骤: 1. 首先需要导入Apache POI依赖包,可以使用Maven进行导入。 2. 创建一个XWPFDocument对象,该对象表示一个Word文档。 3. 获取文档中的所有表格,可以使用getXWPFTableIterator()方法。 4. 遍历所有表格,获取每个表格的行和列,可以使用getRows()和getTableCells()方法。 5. 遍历每个单元格,获取单元格中的文本内容,可以使用getText()方法。 以下是一个简单的代码示例: ``` import org.apache.poi.xwpf.usermodel.*; import java.io.File; import java.io.FileInputStream; import java.util.Iterator; import java.util.List; public class ReadWordTable { public static void main(String[] args) throws Exception { // 创建一个XWPFDocument对象表示一个Word文档 XWPFDocument document = new XWPFDocument(new FileInputStream(new File("test.docx"))); // 获取文档中的所有表格 Iterator<XWPFTable> tableIterator = document.getTablesIterator(); while (tableIterator.hasNext()) { XWPFTable table = tableIterator.next(); System.out.println("Table: " + table.getText()); // 遍历表格中的所有行和列 List<XWPFTableRow> rows = table.getRows(); for (int i = 0; i < rows.size(); i++) { XWPFTableRow row = rows.get(i); List<XWPFTableCell> cells = row.getTableCells(); for (int j = 0; j < cells.size(); j++) { XWPFTableCell cell = cells.get(j); String text = cell.getText(); System.out.println("Row " + i + ", Column " + j + ": " + text); } } } document.close(); } } ``` 这个示例代码可以读取一个名为“test.docx”的Word文档中所有的表格,并输出表格中每个单元格的内容。当然,你需要根据自己的需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值