java集合中的迭代器Iterator和数组内置方法及常见的报错解决方案

 更新时间:2025年02月04日 09:33:26   作者:何人陪我共长生  
文章介绍了Java集合框架中迭代器(Iterator)的使用,以及数组和集合的内置方法,重点解释了在遍历集合时删除元素时可能出现的`ConcurrentModificationException`异常,并说明了如何正确地使用迭代器来删除集合中的元素,感兴趣的朋友跟随小编一起看看吧

删除Map的中某一项报错

package part;
import java.util.HashMap;
import java.util.Set;
public class Java01 {
    public static void main(String[] args) {
        // 为啥这里要使用包装类型 Integer, 而不是int
        HashMap<String, Integer> map = new HashMap();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        // 获取所有键名的集合,返回类型是 Set 类型
        Set<String> Keys = map.keySet();
        // 增强型for循环
        for (String keyName : Keys) {
            // 键名相等的话,删除掉, 导致程序报错了呀。 会报错
            if(keyName == "b"){
              //   map.remove(keyName); 删除会报错的
                map.put("n",11); // 新增也是会报错的
                map.put(keyName, 200); // ok的,但是我们最好还是使用迭代器来操作
            }
        }
    }
}

为啥这里要使用包装类型 Integer, 而不是int

因为: HashMap的键和值必须是对象类型,不能是基本数据类型。
Java 提供了自动装箱(int 转 Integer)和拆箱(Integer 转 int)的功能
int 类型自动装箱后就是 Integer

为哈会报错呢?

我们在循环中途的某一项的时候,不光是删除,新增也会报错的
因为:当你使用 for-each 循环遍历 HashMap 的键集合时
for-each 底层是通过 Iterator 实现的
Iterator 会检查集合是否被修改(通过一个 modCount 变量)来判断
如果发现集合被修改(例添加、删除元素),就会抛出 ConcurrentModificationException

为啥在遍历最后一项的时候删除就不会报错呢

package part;
import java.util.HashMap;
import java.util.Set;
public class Java01 {
    public static void main(String[] args) {
        //  HashMap的键和值必须是对象类型,不能是基本数据类型。 int 类型自动装箱后就是 Integer  
        HashMap<String, Integer> map = new HashMap();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        // 获取所有键名的集合,返回类型是 Set 类型
        Set<String> Keys = map.keySet();
        // 增强型for循环
        for (String keyName : Keys) {
            // 当遍历最后一项的时候,删除就不会报错
            if(keyName == "c"){
                map.remove(keyName);
            }
        }
    }
}

解释:为什么删除最后一项不会报错?

这个跟(ConcurrentModificationException)触发机制
(ConcurrentModificationException) 是通过 modCount 变量来检测集合是否被修改的。
在遍历集合时,Iterator 会检查 modCount 是否与预期值一致。如果不一致(即集合被修改),就会抛出异常。
当你删除最后一项时,Iterator 可能已经完成了遍历,因此不会触发 modCount 的检查。
因此也就不会报错哈

修改数据最好使用迭代器来处理

package part;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class Java01 {
    public static void main(String[] args) {
        // 为啥这里要使用包装类型 Integer, 而不是int
        HashMap<String, Integer> map = new HashMap();
        map.put("a", 1);
        map.put("b", 2);
        map.put("c", 3);
        Set<String> keys = map.keySet();
        // 迭代器
        Iterator<String> it =keys.iterator();
        // hasNext方法用于办法是否存在下一条数据
        while (it.hasNext()) {
            // 获取下一条数据
            String key = it.next();
            // 删除键名是b这一项
            if("b".equals(key)){
                it.remove();
            }
            // 1 null 3
            System.out.println(map.get(key));
        }
        // {a=1, c=3}
        System.out.println(map);
    }
}

使用 removeIf() 方法(Java 8+)迭代

HashMap<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);
map.put("c", 3);
Set<String> keys = map.keySet();
keys.removeIf(keyName -> keyName.equals("c")); // 使用 removeIf
System.out.println(map); // 输出: {a=1, b=2}

使用迭代器能够删除其他项吗?

就是说:我们在循环a这一项的时候,可以删除b这一项的数据吗?
不可以的。
因为:只能够删除当前循环的这一项的。再说一次:只能够删除当前循环的这一项的

将数组转化为字符串 Arrays.toString()

package part;
import java.util.Arrays;
public class Java01 {
    public static void main(String[] args) {
        // 声明并初始化一个 int 数组
        int[] is= {1, 2, 3, 4, 5};
        // 转化为字符串 [1, 2, 3, 4, 5]
        String str = Arrays.toString(is);
        System.out.println(str);
        // [I@28d93b30 是hashCode的内存地址
        System.out.println(is);
    }
}

将数组转化为集合以及升序

package part;
import java.util.Arrays;
import java.util.List;
public class Java01 {
    public static void main(String[] args) {
        // 将数组转化为集合
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        int[] arr =  {4,1,-3,10 };
        // Arrays.sort 默认是升序的哈,会影响原始数组的哈,与js不同的
        Arrays.sort(arr);
        // [-3, 1, 4, 10]
        System.out.println(Arrays.toString(arr));
    }
}

二分查找法,查找的是排序后的位置

package part;
import java.util.Arrays;
import java.util.List;
public class Java01 {
    public static void main(String[] args) {
        int[] arr =  {4,1,-3,10 };
        Arrays.sort(arr);
        // [-3, 1, 4, 10]
        System.out.println(Arrays.toString(arr));
        // 查询4的位置
        int index = Arrays.binarySearch(arr, 4);
        // 2
        System.out.println(index);
    }
}

2个数组项比较

package part;
import java.util.Arrays;
import java.util.List;
public class Java01 {
    public static void main(String[] args) {
        int[] arr1 =  {4,1,-3,10 };
        int[] arr2 = {4,1,10, -3};
        // 会比较2个数组是否相等,会一对一进行比较。 第2项的-3和第2项的10不相等,返回flase
        System.out.println(Arrays.equals(arr1,arr2)); // false
    }
}
package part;
import java.util.Arrays;
import java.util.List;
public class Java01 {
    public static void main(String[] args) {
        int[] arr1 = {4, 1, -3, 10};
        int[] arr2 = {4, 1, 10, -3};
        //arr1, 0, 2表示从arr1数组中,从0开始取,取前2个。 arr2, 0, 2表示从arr2数组中,从0开始取,取前2个
        // 特别需要注意一点的是: 是在 JDK 9 中引入的。如果你使用的是 JDK 8 或更早版本,这个方法会报错。
        System.out.println(Arrays.equals(arr1, 0, 2, arr2, 0, 2)); // 输出: true
    }
}

ArrayList 集合默认时长度10,你设置容器大小必须大于等于0。如果是负数会报错

package part;
import java.util.ArrayList;
public class Java01 {
    public static void main(String[] args) {
        ArrayList<String > list2 = new ArrayList<String>(0);
        System.out.println(list2); // []
       ArrayList<String> list1 = new ArrayList<String>(-1);
       System.out.println(list1); //  ava.lang.IllegalArgumentException 非法参数异常
    }
}

ArrayList的访问范围是[0,长度-1]

package part;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Java01 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("A");
        list.add("B");
        list.add("C");
        // 访问的范围是[0,长度-1]
        System.out.println(list.get(2));
        // IndexOutOfBoundsException 索引超出异常
        System.out.println(list.get(3));
    }
}

LinkedList的长度是0,使用get(0)和getFirst访问报错

package part;
import java.util.LinkedList;
public class Java01 {
    public static void main(String[] args) {
       LinkedList<String> list = new LinkedList<String>();
       //报错 IndexOutOfBoundsException
       System.out.println(list.get(0));
       // list的长度是0, 现在你获取第1项,这样的操作跟索引越界相似。同样也是会报错的
        // java.util.NoSuchElementException
       System.out.println(list.getFirst());
    }
}

JAVA 复制 全屏

HashMap在循环的时候删除,新增数据会报错

package part;
import java.util.HashMap;
import java.util.LinkedList;
public class Java01 {
    public static void main(String[] args) {
        HashMap map = new HashMap();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        // HashMap一旦开始循环,那么如果删除,新增数据,就会发生错误
        for (Object key : map.keySet()) {
            if(key.equals("b")){
               // map.remove(key); 删除数据报错
               //  map.put("d",4); 新增数据报错
                map.put(key,4); // 修改数据不会报错的哈
            }
        }
        // 我们可以使用迭代器还解决这样的问题哈。
        System.out.println(map);
    }
}

到此这篇关于java集合中的迭代器Iterator和数组内置方法以及常见的报错的文章就介绍到这了,更多相关java迭代器Iterator和数组内置方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java使用servlet实现验证码

    java使用servlet实现验证码

    这篇文章主要介绍了java使用servlet实现验证码,简单实用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • mybatis映射表结构的使用

    mybatis映射表结构的使用

    MyBatis通过表结构映射实现数据库操作,本文就来介绍一下mybatis映射表结构的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • java实现点击按钮事件弹出子窗口

    java实现点击按钮事件弹出子窗口

    这篇文章主要为大家详细介绍了java实现点击按钮事件弹出子窗口,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • mybatis拦截器注册初始化编写示例及如何生效详解

    mybatis拦截器注册初始化编写示例及如何生效详解

    这篇文章主要为大家介绍了mybatis拦截器注册初始化编写示例及如何生效详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • SpringBoot个性化配置的方法步骤

    SpringBoot个性化配置的方法步骤

    这篇文章主要介绍了SpringBoot个性化配置的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • Java中的五种引用类型详解

    Java中的五种引用类型详解

    Java中的五种引用类型:强引用、软引用、弱引用、虚引用和Final引用,分别用于管理对象的生命周期,帮助垃圾回收器更高效地回收不再使用的对象
    2024-12-12
  • Java快速排序的实现方法示例

    Java快速排序的实现方法示例

    快速排序是对冒泡排序的一种改进,下面这篇文章主要给大家介绍了关于Java快速排序的实现方法,文中通过代码介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-03-03
  • 设计模式之构建(Builder)模式 建造房子实例分析

    设计模式之构建(Builder)模式 建造房子实例分析

    构建模式主要用来针对复杂产品生产,分离部件构建细节,以达到良好的伸缩性,考虑到设计模式来源于建筑学,因此举一个建造房子的例子,需要的朋友可以参考下
    2012-12-12
  • SpringBoot 如何从容器中获取对象

    SpringBoot 如何从容器中获取对象

    这篇文章主要介绍了SpringBoot 如何从容器中获取对象,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Spring JPA find分页示例详解

    Spring JPA find分页示例详解

    这篇文章主要为大家介绍了Spring JPA find分页示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04

最新评论