首页 > 其他分享 >List的remove()方法详解

List的remove()方法详解

时间:2024-05-04 21:55:41浏览次数:20  
标签:nameList name List remove add 详解 李四

https://blog.csdn.net/anxin_hw/article/details/128312846

一、错误使用场景

1、普通for循环遍历List删除指定元素,list.remove(index)

示例:将姓张的名字移除掉

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (int i = 0; i < nameList.size(); i++) {
     String name = nameList.get(i);
     System.out.println("当前遍历对象==="+name);
     if (name.startsWith("张")) {
         nameList.remove(i);
     }
}
System.out.println(nameList);

   输出结果:

 【李四】【张八】遍历被跳过,【张八】没有被成功移除

原因分析:

List调用remove(index)方法后,会移除index位置上的元素,之后的所有元素依次前移,当移除完【张三】时,【李四】变成了数组的第一位,此时的索引应该要index-1才能获取到【李四】。所以每移除一个元素时就需要把index-1,否则原来索引为index+1的元素就无法遍历到。

2、foreach遍历List删除元素

示例:同上

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (String name : nameList) {
    System.out.println("当前遍历对象==="+name);
    if (name.startsWith("张")) {
        nameList.remove(name);
    }
}
System.out.println(nameList);

  输出结果:

 

原因分析:

foreach循环实际上是迭代,使用list.remove(item)方法后,list 对象的modCount值进行了修改,而 list对象的迭代器中的expectedModCount值没有修改,所以抛出了异常

3、直接使用list.remove(object)

示例: 将张三从数组中移除

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张三");
nameList.add("张三");
nameList.remove("张三");
System.out.println(nameList);

  

输出结果:[李四, 王五, 赵六, 张三, 张三]

原因分析:

list.remove(object)的逻辑和list.remove(index)大致相同:元素依次遍历,数组中存在与入参对象相等的元素就移除,之后的所有元素依次前移,返回true,若不存在与入参相等的元素,返回false。

二、正确使用方法

1、 使用list.removeIf()方法

removeIf()的入参是一个过滤条件,用来判断需要移除的元素是否满足条件。

原理:方法中设置了一个removeSet,把满足条件的元素索引坐标都放入removeSet,然后统一对removeSet中的索引进行移除

示例:将姓张的名字移除掉

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
nameList.removeIf(o->o.startsWith("张"));
System.out.println(nameList);

  输出结果:[李四, 王五, 赵六]

2、使用迭代器Iterator移除元素

迭代器是一个链表,直接使用remove操作不会出现问题

示例:同上

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
Iterator<String> iterator = nameList.iterator();
while (iterator.hasNext()) {
    if (iterator.next().startsWith("张")) {
        iterator.remove();
    }
}
System.out.println(nameList);

  输出结果:[李四, 王五, 赵六]

3、使用list.removeAll()方法

定义一个需要移除的数组,for循环内将需要移除的元素收集在定义的数组中,for循环结束后直接removeAll()

示例:同上

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
List<String> removeList = new ArrayList<>();
for (String name : nameList) {
    if (name.startsWith("张")) {
        removeList.add(name);
    }
}
nameList.removeAll(removeList);
System.out.println(nameList);

  输出结果:[李四, 王五, 赵六]

4、倒序遍历元素然后删除

正序删除元素会移位那我们转变思维倒序遍历

示例:

List<String> nameList = new ArrayList<>(Arrays.asList("张三", "李四", "王五", "赵六"));
nameList.add("张七");
nameList.add("张八");
for (int i = nameList.size() - 1; i >= 0; i--) {
    String name = nameList.get(i);
    System.out.println("当前遍历对象===" + name);
    if (name.startsWith("张")) {
        nameList.remove(i);
    }
}
System.out.println(nameList);

  输出结果:

 

三、总结

1、使用普通for循环删除元素时需要注意索引会变化的问题

2、list删除元素时建议使用迭代器Iterator或者removeIf()方法

标签:nameList,name,List,remove,add,详解,李四
From: https://www.cnblogs.com/Dongmy/p/18172699

相关文章

  • CMakeLists.txt --- install使用
    例:cmake_minimum_required(VERSION3.9)project(test)set(CMAKE_BUILD_TYPEDebug)add_library(hahatest.cpp)install(TARGEThahaDESTINATION/home/linxisuo/project/test)install(DIRECTORY${CMAKE_SOURCE_DIR}/testDESTINATION/home/linxisuo)说明:1.安装......
  • CMakeListx.txt --- include_directories和target_include_directories命令
    1. include_directories语法include_directories([AFTER|BEFORE][SYSTEM]dir1[dir2...])作用将指定目录添加到编译器的头文件搜索路径之下,指定的目录被解释成当前源码路径的相对路径。参数默认情况下,include_directories命令会将目录添加到列表最后,可以通过命令设置......
  • CMakeLists.txt --- 导入接口库(预编译库)
    以接口库的方式导入预编译库cmake_minimum_required(VERSION3.9)project(test)set(CMAKE_BUILD_TYPEDebug)set(CMAKE_C_FLAGS"$ENV{CFLAGS}-O2-Wall-pthread")set(CMAKE_CXX_FLAGS"$ENV{CFLAGS}-O2-Wall-pthread-std=c++11-std=gnu++11")#设置mo......
  • python教程3.1:数据类型:字符串+列表list
    一、字符串字符串是⼀个有序的字符的集合,⽤于在计算机⾥存储和表示⽂本信息 常用操作二、列表list[]内以逗号分隔,按照索引,存放各种数据类型,每个位置代表⼀个元素特征 1、增加操作   追加,数据会追加到尾部 2、删除操作3、修改操作 4、查找操作 如果......
  • 【c语言】编译过程详解
    为什么我们编写的C语言要进行编译❓什么是编译❓编译时发生了什么❓机器无法理解我们编写的C语言,而编译就是将面向人类的高级语言转换成为面向机器的机器语言的过程,图1是GCC编译器进行编译的过程,编译时主要分为了4个阶段,每个阶段的具体作用将在接下来进行介绍。图1......
  • iptables使用详解(centos7)
    iptables使用详解(centos7)小百菜已于2024-03-2114:40:02修改阅读量7.2k收藏22点赞数2文章标签:iptables限速版权GitCode开源社区文章已被社区收录加入社区我们需要安装iptables-services,用来启动和停止iptables服务防火墙配置文件/etc/sysconfig/iptables查......
  • 详解csrf(跨站请求伪造)
    1.什么是csrf(csrf攻击原理)?用户正常访问A网站,A网站设置cookie被用户浏览器保存用户不关闭浏览器,直接访问恶意网站,该恶意网站内隐藏式内嵌了A网站接口的请求链接触发该请求链接,自动携带浏览器保存的cookie,请求成功。2.涉及的基础知识我们先梳理下上面所涉及的一些......
  • 高效遍历:C++中分隔字符串单词的3种方法详解与实例
     概述:在C++中,遍历由空格分隔的字符串的单词有多种方法,包括使用`std::istringstream`、手动遍历字符和正则表达式。其中,`std::istringstream`是简单高效的选择,通过流提取单词。手动遍历字符较为繁琐,正则表达式方法更灵活但可能有性能开销。根据实际需求选择方法,本文提供了清晰......
  • Redis持久化、主从与哨兵架构详解
    参考图灵课堂https://zhuanlan.zhihu.com/p/443951927https://blog.csdn.net/weixin_37548768/article/details/124538778?spm=1001.2014.3001.5502https://www.runoob.com/redis/redis-transactions.html   redis支持持久化到磁盘,这样可用进一步保证数据的完整性。re......
  • 前端 Vue-cli中 vue.config.js 的配置详解
    Vue-cli3/Vue-cli4 目录结构├──README.md #说明|--dist #打包后文件夹├──babel.config.js #babel语法编译├──package-lock.json├──public #静态文件夹,这类资源将会直接被拷贝,而不会经过webpack的......