详解Java中List的正确的删除方法

目录
  • 简介
  • 实例
  • 正确方法
    • 法1:for的下标倒序遍历
    • 法2: list.stream().filter().collect()
    • 法3: iterator迭代器
  • 错误方法
    • 法1:for(xxx : yyy)遍历
    • 法2:for的下标正序遍历
  • 原因分析

简介

本文介绍Java的List的正确的删除方法。

实例

需求:有如下初始数据,将list中的所有数据为"b"的元素删除掉。即:填充removeB()方法

package com.example.a;

import java.util.ArrayList;
import java.util.List;

public class Demo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("d");

        removeB(list);
    }

    private static void removeB(List<String> list) {
        // 待填充
    }
}

正确方法

法1:for的下标倒序遍历

private static void removeB(List<String> list) {
    for (int i = list.size() - 1; i >= 0; i--) {
        if ("b".equals(list.get(i))) {
            list.remove(i);
        }
    }
    System.out.println(list);
}

结果

[a, c, d]

法2: list.stream().filter().collect()

private static void removeB(List<String> list) {
    List<String> newList = list.stream()
            .filter(e -> !"b".equals(e))
            .collect(Collectors.toList());
    System.out.println(newList);
}

结果

[a, c, d]

法3: iterator迭代器

private static void removeB(List<String> list) {
    Iterator<String> it = list.iterator();
    while (it.hasNext()) {
        String s = it.next();
        if ("b".equals(s)) {
            it.remove();
        }
    }
    System.out.println(list);
}

结果

[a, c, d]

错误方法

法1:for(xxx : yyy)遍历

private static void removeB(List<String> list) {
    for (String s : list) {
        if ("b".equals(s)) {
            list.remove(s);
        }
    }
    System.out.println(list);
}

结果(报异常)

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at com.example.a.Demo.removeB(Demo.java:18)
    at com.example.a.Demo.main(Demo.java:14)

法2:for的下标正序遍历

private static void removeB(List<String> list) {
    for (int i = 0; i < list.size(); i++) {
        if ("b".equals(list.get(i))) {
            list.remove(list.get(i));
        }
    }
    System.out.println(list);
}

结果(有的没有删除掉)

[a, b, c, d]

原因分析

需求:通过遍历把list集合的所有数据删除掉。

package com.example.a;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class Demo {
    private static List<String> list = new ArrayList<>();

    public static void main(String[] args) {
        reset();
        // method1();
        // method2();
        // method3();
        // method4();
    }

    private static void reset(){
        list.clear();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
    }

    /**
     * 方法一:遍历删除第i个元素(错误版)
     * 执行结果:没有完全删除。打印结果:[b, d]
     */
    /**
     * 下面遍历操作过程如下:
     * i = 0    list.size() == 5   执行完第一次list.remove(0);  list剩下[b,c,d,e]
     * i = 1    list.size() == 4   执行完第二次list.remove(1);  list剩下[b,d,e]
     * i = 2    list.size() == 3   执行完第三次list.remove(2);  list剩下[b,d]
     * i = 3    list.size() == 2   i > list.size()所以条件不满足,最后剩下[b,d]
     */
    public static void method1() {
        for (int i = 0; i< list.size(); i++) {
            list.remove(i);
        }
        System.out.println(list);
    }

    /**
     * 方法二:删除第0个元素(错误版)
     *  执行结果:元素没有删除。打印结果:[d, e]
     */
    /**
     * 下面遍历操作过程如下:
     * i = 0    list.size() == 5   执行完第一次list.remove(0);  list剩下[b,c,d,e]
     * i = 1    list.size() == 4   执行完第二次list.remove(0);  list剩下[c,d,e]
     * i = 2    list.size() == 3   执行完第三次list.remove(0);  list剩下[d,e]
     * i = 3    list.size() == 2   i > list.size()所以条件不满足,最后剩下[d,e]
     */
    public static void method2() {
        for (int i = 0; i< list.size(); i++) {
            list.remove(0);
        }
        System.out.println(list);
    }

    /**
     * 方法三:只取一次长度删除第i个(错误版)
     * 执行结果:报错。打印结果:
     *   Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 2
     */
    /**
     * 只求取list.size()长度一次
     * i == 0 len == 5 list.remove(0) list剩下[b,c,d,e]
     * i == 1 len == 5 list.remove(1) list剩下[b, d,e]
     * i == 2 len == 5 list.remove(2) list剩下[b, d]
     * i == 3 len == 5 list.remove(3) list因为没有第四个元素,于是报索引越界错误
     */
    public static void method3() {
        int len = list.size();
        for (int i = 0; i < len; i++) {
            list.remove(i);
        }
        System.out.println(list);
    }

    /**
     * 方法四:只取一次长度删除第0个(正确版)
     * 执行结果:完全删除。打印结果:[]
     */
    /**
     * 下面遍历操作过程如下:
     * i = 0    len == 5   执行完第一次list.remove(0);  list剩下[b,c,d,e]
     * i = 1    len == 5   执行完第二次list.remove(0);  list剩下[c,d,e]
     * i = 2    len == 5   执行完第三次list.remove(0);  list剩下[d,e]
     * i = 3    len == 5   执行完第四次list.remove(0);  list剩下[e]          
     * i = 4    len == 5   执行完第五次list.remove(0);   list剩下[]
     */
    public static void method4() {
        int len = list.size(); // 保证只获取一次长度
        for (int i = 0; i< len; i++) {
            list.remove(0);
        }
        System.out.println(list);
    }
}

以上就是详解Java中List的正确的删除方法的详细内容,更多关于Java List删除方法的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java中List遍历删除元素remove()的方法

    今天碰见根据条件进行list遍历remove的问题,第一时间就是简单for循环remove,只知道这么写不行,不安全,可是为什么呢?你想过吗?下面就关于List遍历remove的问题,深挖一下! 一.几种常见的遍历方式 1.普通for循环 2.高级for循环 3.iterator和removeIf 4.stream() 5.复制 6.普通for循环 --> 倒序方式 二.源码篇 1.普通for循环出错原因 public boolean remove(Object o) { if (o == nu

  • 2种Java删除ArrayList中的重复元素的方法

    这篇文章将给出两种从ArrayList中删除重复元素的方法,分别是使用HashSet和LinkedHashSet. ArrayList是Java中最常用的集合类型之一.它允许灵活添加多个null元素,重复的元素,并保持元素的插入顺序.在编码时我们经常会遇到那种必须从已建成的ArrayList中删除重复元素的要求. 方法1:使用HashSet删除ArrayList中重复的元素 在该方法中,我们使用HashSet来删除重复的元素.如你所知,HashSet不允许有重复的元素.我们使用HashSet的这

  • java集合类arraylist循环中删除特定元素的方法

    在项目开发中,我们可能往往需要动态的删除ArrayList中的一些元素. 一种错误的方式: <pre name="code" class="java">for(int i = 0 , len= list.size();i<len;++i){ if(list.get(i)==XXX){ list.remove(i); } } 上面这种方式会抛出如下异常: Exception in thread "main" java.lang.I

  • java中循环删除list中元素的方法总结

    印象中循环删除list中的元素使用for循环的方式是有问题的,但是可以使用增强的for循环,然后今天在使用时发现报错了,然后去科普了一下,再然后发现这是一个误区.下面就来讲一讲..伸手党可直接跳至文末.看总结.. JAVA中循环遍历list有三种方式for循环.增强for循环(也就是常说的foreach循环).iterator遍历. 1.for循环遍历list for(int i=0;i<list.size();i++){ if(list.get(i).equals("del")

  • Java list利用遍历进行删除操作3种方法解析

    这篇文章主要介绍了Java list利用遍历进行删除操作3种方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java三种遍历如何进行list的便利删除: 1.for循环: 常见初五写法:(由于下标问题达不到想要效果) for(int i=0;i<list.size();i++){ if(list.get(i).equals("del")) list.remove(i); } 应该改为:(倒序操作避免下标问题) int s

  • 详解Java中List的正确的删除方法

    目录 简介 实例 正确方法 法1:for的下标倒序遍历 法2: list.stream().filter().collect() 法3: iterator迭代器 错误方法 法1:for(xxx : yyy)遍历 法2:for的下标正序遍历 原因分析 简介 本文介绍Java的List的正确的删除方法. 实例 需求:有如下初始数据,将list中的所有数据为"b"的元素删除掉.即:填充removeB()方法 package com.example.a; import java.util.Ar

  • 详解Java中异步转同步的六种方法

    目录 一.问题 应用场景 二.分析 三.实现方法 1.轮询与休眠重试机制 2.wait/notify 3.Lock Condition 4.CountDownLatch 5.CyclicBarrier 6.LockSupport 一.问题 应用场景 应用中通过框架发送异步命令时,不能立刻返回命令的执行结果,而是异步返回命令的执行结果. 那么,问题来了,针对应用中这种异步调用,能不能像同步调用一样立刻获取到命令的执行结果,如何实现异步转同步? 二.分析 首先,解释下同步和异步 同步,就是发出一个调

  • 详解Java中的println输入和toString方法的重写问题

    目录 println()直接打印 toString的使用 其他的一些情况 println()直接打印 我们都知道println()如果打印的是基本数据类型的话直接打印出来的就是值,你如果是引用数据类型呢? 除掉这四类八种基本类型,其它的都是对象,也就是引用类型,包括数组. 让我们来测试一下 public class test1 { public static void main(String[] args) { int[] ret = {1, 2, 3, 4}; System.out.print

  • 详解Java中@Override的作用

    详解Java中@Override的作用 @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读: 2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如果没写@Override,而你下面的方法名又写错了,这时你的编译器是可以编译通过的,因为编译器以为这个方法是你的子类中自己增加的方法. 举例:在重写父类的onCreate时,在方法前面加上@Override 系统可以帮你检查方法的正确性. @Overr

  • 详解java中接口与抽象类的区别

    详解java中接口与抽象类的区别 1.abstract class 在 Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系.但是,一个类却可以实现多个interface. 2.在abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在 interface中一般不定义数据成员),所有的成员方法都是abstract的. 3.abstract c

  • 详解Java中AbstractMap抽象类

    jdk1.8.0_144 下载地址:http://www.jb51.net/softs/551512.html AbstractMap抽象类实现了一些简单且通用的方法,本身并不难.但在这个抽象类中有两个方法非常值得关注,keySet和values方法源码的实现可以说是教科书式的典范. 抽象类通常作为一种骨架实现,为各自子类实现公共的方法.上一篇我们讲解了Map接口,此篇对AbstractMap抽象类进行剖析研究. Java中Map类型的数据结构有相当多,AbstractMap作为它们的骨架实现实

  • 详解Java中的BigDecimal

    今天碰到一个问题,金额计算用double类型会丢失经度,就改用了BigDecimal类型,这个类型之前用的比较少,没怎么接触.就到网上看了一下相关教程,写个总结记一下. BigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作. BigDecimal构造方法 1.public BigDecimal(double val) 将double表示形式转换

  • 详解Java中方法next()和nextLine()的区别与易错点

    1.基本语法 1.1基本使用方法 本篇博客重点nextLine()会读取换行('\r'),但是不会进行输出. Java中Scanner类中的方法next()和nextLine()都是吸取输入台输入的字符,区别: next()不会吸取字符前/后的空格/Tab键,只吸取字符,开始吸取字符(字符前后不算)直到遇到空格/Tab键/回车截止吸取: nextLine()吸取字符前后的空格/Tab键,回车键截止. 输入两行字符串: 我爱学JAVA 我真的很爱爱学JAVA 我真的很爱很爱学JAVA 期望输出结果

  • 详解Java中的hashcode

    一.什么是hash Hash,一般翻译做散列.杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值.简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数. 这个说的有点官方,你就可以把它简单的理解为一个key,就像是map的key值一样,是不可重复的. 二.hash有什么用?,

  • 详解Java中JSON数据的生成与解析

    一.什么是JSON JSON: JavaScript Object Notation JS对象简谱,是一种类似于XML的语言.相比于XML,它更小.更快.更易解析.主要用于项目前端和Server的网络数据传输. 二.JSON的语法 对象 一个对象,由一个大括号表示{},{}中通过一个个的键值对来描述对象的属性 注意: 键与值之间使用冒号连接,多个键值对之间使用逗号分隔. 键值对的键,应使用引号引住(通常Java解析时,键不使用引号会报错,而JS能正确解析):键值对的值,可以是JS中的任意数据类型

随机推荐