List移除元素的四种方式

List 移除某个元素

四种方式:

  • 方式一,使用 Iterator ,顺序向下,如果找到元素,则使用 remove 方法进行移除。
  • 方式二,倒序遍历 List ,如果找到元素,则使用 remove 方法进行移除。
  • 方式三,正序遍历 List ,如果找到元素,则使用 remove 方法进行移除,然后进行索引 “自减”。
  • 方式四,使用jdk1.8新增的Stream流操作
    1.Iterator 迭代器
	@Testpublic void fun9(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");// 获取迭代器Iterator<String> it = list.iterator();while(it.hasNext()){String str = it.next();if("关羽".equals(str)){it.remove();}}System.out.println(list);}

2.倒序遍历

	@Testpublic void fun10(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");for (int i = list.size() - 1; i > 0; i--) {if("关羽".equals(list.get(i))){list.remove(i);}}System.out.println(list);}

3.正序遍历

 	@Testpublic void fun11(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");for (int i = 0; i < list.size(); i++) {if("关羽".equals(list.get(i))){list.remove(i);i--;}}System.out.println(list);}

4.Stream流操作(JDK 1.8 +)

	@Testpublic void fun8(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");// 筛选出不是“关羽” 的集合list = list.stream().filter(e -> !"关羽".equals(e)).collect(Collectors.toList());System.out.println("method4|list=" + list);}

问题:

1.为什么不能使用forEach

	@Testpublic void fun5(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");for (String str :list) {if ("张飞".equals(str)){list.remove(str);}}System.out.println(list);}

在这里插入图片描述
原因:
         foreach方式遍历元素的时候,是生成iterator,然后使用iterator遍历。在生成iterator的时候,会保存一个expectedModCount参数,这个是生成iterator的时候List中修改元素的次数。如果你在遍历过程中删除元素,List中modCount就会变化,如果这个modCount和exceptedModCount不一致,就会抛出异常。这个是为了安全的考虑。如果使用iterator遍历过程中,使用List修改了元素,可能会出现不正常的现象。如果使用iterator的remove方法则会正常,因为iterator的remove方法会在内部调用List的remove方法,但是会修改excepedModCount的值,因此会正常运行。

2.为什么forEach 删除倒数第二元素不会出现异常

 	@Testpublic void fun12() {List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");for (String str:list) {if("关羽".equals(str)){list.remove(str);}System.out.println(str);}}

在这里插入图片描述
仔细观察发现集合最后一个元素(“张飞”)并没有被遍历出来,因为当我们移除倒数第二个元素(“关羽”)时 cursor(游标)为 4 ,list 中size 属性的值会发生变化(5 - 1 = 4)变为 4,所以下面代码返回 false ,也就不会继续向下遍历。这也是能够正常执行的原因,因为如果继续遍历就会出现问题1 中的情况,在进行checkForComodification() 时,因为 modCount 发生了变化,而expectedModCount 并没有发生变化,所以会出现 ConcurrentModificationException异常。

public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}
 public boolean hasNext() {return cursor != size;}
public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}
final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}

3 普通正序 for 循环为什么要 i –

因为遍历过程中进行remove 操作时,该位置后面的元素会挤到前面来,这时候会发生一种情况就是原来元素的位置会被他后面的元素取代,而该位置已经遍历过了,所以该元素不会背遍历。 所以要进行 i-- 操作从该位置重新遍历。

	@Testpublic void fun11(){List<String> list = new ArrayList<>();list.add("赵云");list.add("黄忠");list.add("马超");list.add("关羽");list.add("张飞");for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));if("关羽".equals(list.get(i))){list.remove(i);}}System.out.println(list);}

就是下面的情况 “张飞” 不见了…
在这里插入图片描述

4 为什么倒序for 循环可以

当我们倒序遍历元素的时候,无论删除元素之后的元素怎么移动,之前的元素对应的索引(index)是不会发生变化的,所以在删除元素的时候不会发生问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/12939.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

括号生成(力扣)递归 JAVA

目录 题目描述&#xff1a;纯递归解法&#xff1a;递归 回溯&#xff1a; 题目描述&#xff1a; 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a…

spring重点标签有哪些

<bean>标签 id属性:在容器中Bean实例的唯一标识&#xff0c;不允许重复 class属性:要实例化的Bean的全限定名 scope属性:Bean的作用范围&#xff0c;常用是singleton(默认)和prototype <property>标签:属性注入 name属性:属性名称 value属性:注入的普通属性值 ref属…

Netty核心技术九--TCP 粘包和拆包及解决方案

1. TCP 粘包和拆包基本介绍 **TCP是面向连接的&#xff0c;面向流的&#xff0c;提供高可靠性服务。收发两端&#xff08;客户端和服务器端&#xff09;都要有一一成对的socket&#xff0c;因此&#xff0c;发送端为了将多个发给接收端的包&#xff0c;更有效的发给对方&#x…

爆肝整理,Docker容器测试-常见问题+解决(汇总)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 问题1&#xff1a…

React + TypeScript 实践

主要内容包括准备知识、如何引入 React、函数式组件的声明方式、Hooks、useRef<T>、useEffect、useMemo<T> / useCallback<T>、自定义 Hooks、默认属性 defaultProps、Types or Interfaces、获取未导出的 Type、Props、常用 Props ts 类型、常用 React 属性类…

TensorFlow: mode.save()报错 non-trackable object: (None, None)

问题描述 环境&#xff1a;tensorflow2.2.0 执行model.save(), 报错 ...non-trackable object: (None, None)... 解决办法 搞了半天没有找到好的办法&#xff0c;只能通过升级搞定 pip uninstall tensorflow pip install tensorflow2.6.0 pip install --upgrade keras2.6…

数据结构--线性表(顺序表、单链表、双链表、循环链表、静态链表)

前言 学习所记录&#xff0c;如果能对你有帮助&#xff0c;那就泰裤辣。 目录 1.线性表概念 定义 基本操作 2.顺序表 定义 顺序表的实现--静态分配 动态分配 顺序表的特点 顺序表的插入和删除 顺序表的查找 按位查找 按值查找 3.单链表 定义 单链表的初始化 不带…

在Windows环境下安装Elasticsearch 8.8.2

Elasticsearch是一种开源的分布式搜索和分析引擎&#xff0c;被广泛应用于构建实时搜索、日志分析、数据可视化等应用。本文将详细介绍如何在Windows环境下安装和配置Elasticsearch 8。 安装Elasticsearch 步骤1&#xff1a;准备工作 在开始安装之前&#xff0c;确保已满足以…

gitee注册以及使用的简单教程

目录 1.gitee是什么&#xff1f; 2. gitee怎么注册? 3.gitee创建仓库 4.gitee怎么提交代码? 5. git的三板斧 1.gitee是什么&#xff1f; 基于Git的代码托管和研发协作平台上面可以托管个人或者公司的代码和开源项目。国外有github&#xff0c;国内有giteegithub经常出现…

docker安装postgresql

docker run --name postgres -e POSTGRES_PASSWORD123456 -p 5432:5432 -v /mydata/postgres/pgdata:/var/lib/postgresql/data -d postgres 修改postgresql最大连接数 vim /mydata/postgres/pgdata/postgresql.conf 附:常用连接数查看命令 -- 1.查看当前配置的最大连接数 s…

4通道AD采集子卡模块有哪些推荐?

FMC134是一款4通道3.2GSPS&#xff08;2通道6.4GSPS&#xff09;采样率12位AD采集FMC子卡模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4规范&#xff0c;可以作为一个理想的IO模块耦合至FPGA前端&#xff0c;16通道的JESD204B接口通过FMC连接器连接至FPGA的高速串行…

为了实现上网自由,我做了一个多功能串口服务器

项目作者&#xff1a;小华的物联网嵌入式之旅 介绍&#xff1a;从事电气自动化行业&#xff0c;多次获得物联网设计竞赛&#xff0c;爱好嵌入式设计开发&#xff0c;物联网开发。 设计方案思路的由来&#xff0c;是因为我们现在的开发板基本需要通过串口与WIFI模组或以太网模…