java集合中的迭代器Iterator和数组内置方法及常见的报错解决方案
删除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和数组内置方法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
springboot中使用Feign整合nacos,gateway进行微服务之间的调用方法
这篇文章主要介绍了springboot中使用Feign整合nacos,gateway进行微服务之间的调用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-03-03Spring Security代码实现JWT接口权限授予与校验功能
本文给大家介绍Spring Security代码实现JWT接口权限授予与校验功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧2019-12-12SpringBoot中的ImportSelector类动态加载bean详解
这篇文章主要介绍了SpringBoot中的ImportSelector类动态加载bean详解,ImportSelector接口是spring中导入外部配置的核心接口,根据给定的条件(通常是一个或多个注释属性)判定要导入那个配置类,在spring自动化配置和@EnableXXX中都有它的存在,需要的朋友可以参考下2024-01-01聊聊@RequestMapping和@GetMapping @PostMapping的区别
这篇文章主要介绍了@RequestMapping和@GetMapping及@PostMapping的区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-08-08
最新评论