java容器中遍历循环Iterator 和 Foreach 循环

最近遇到这样一个问题,要删除一个集合中的某个元素,该怎么解决?

我自己写了两段代码来删除,都报了一个错java.util.ConcurrentModificationException;为了让更多可能没注意到这个点的程序猿注意一下,我在这里分享下~

先看代码

 1 package com.zwt1234;
 2
 3 import java.util.HashSet;
 4 import java.util.Iterator;
 5 import java.util.Set;
 6
 7 public class IteratorTest {
 8     public static void main(String[] args) {
 9         Set<Object> s = new HashSet<Object>(0);
10         s.add(new Man("小明", 12));
11         s.add(new Man("小李", 15));
12         s.add(new Man("小华", 21));
13         validateIterator(s);
14 //        validateForeach(s);
15     }
16
17     /**
18      * 验证Iterator接口的方法
19      * iterator进入循环后,相当于线程上了一把锁,谁都不让进,只能用iterator自己的对象操作数据
20      * 因此下面用s.remove(man)是,程序报错
21      * @param s
22      */
23     public static void validateIterator(Set<Object> s) {
24         Iterator<Object> iter = s.iterator();
25         while (iter.hasNext()) {
26             Man man = (Man)iter.next();
27             System.out.println(man);
28             if (man.name.equals("小李")) {
29                 iter.remove();
30                 // s.remove(man);//此时程序报错java.util.ConcurrentModificationException
31             }
32         }
33         System.out.println("------------------------");
34         /*
35          * 执行上面删除操作后重新打印s集合中元素,印证操作
36          */
37         iter = s.iterator();
38         while (iter.hasNext()) {
39             System.out.println(iter.next());
40         }
41     }
42
43     /**
44      * 验证foreach循环
45      * foreach循环相对iterator在查询上面更加方便了,因为代码量少了;
46      * 但是在岁数据操作上面比不过iterator
47      * @param s
48      */
49     public static void validateForeach(Set<Object> s) {
50         for (Object obj:s) {
51             Man man = (Man)obj;
52             System.out.println(man);
53             if (man.name.equals("小李")) {
54                 s.remove(man);//这里同样是不让删除的,因为foreach循环底层就是用的iterator的实现方式
55             }
56         }
57     }
58 }
59
60 class Man {
61     String name;
62     int age;
63
64     Man(String name, int age) {
65         this.name = name;
66         this.age = age;
67     }
68
69     @Override
70     public String toString() {
71         return "Man [name=" + name + ", age=" + age + "]";
72     }
73 }

下面我们来分析下我们这段代码

  1.首先我用,Iterator来实现的删除,开始的时候,在遍历到存入的对象名为小李的时候,我就让这个对象,在Set集合s中删除,在if语句里面,面对2个问题,集合s有给我们提供一个remove()方法,还有iterator也给我们提供了一个remove()方法,我们用哪个?

  最开始的时候我选用的是Set集合给的方法,可是在运行的时候,结果就报错了,而改用iterator提供的方法是可以正确运行的,正常删除了我所需要删除的对象。

  结果总结:说明在使用iterator迭代器的时候,我们需要删除集合中数据,使用的应该是Iterator的remove()方法,因为使用iterator的时候,就相当于给线程给资源上了一把锁,只有iterator本身可以去删除数据,而集合线程是无法在iterator占用资源的时候对资源进行删除的。

  2.同样的foreach增强for循环的实现删除的时候,我也去实现了下。

  因为foreach循环没有给我们提供remove()方法,因此我们直接使用Set集合里面给我们提供的删除方法,发现也是会报和iterator同样的错误,因此,证明foreach循环是不适合进行数据的删除的。

  (对于上面的代码操作结果,就请大家copy一下,直接运行就能查看结果了,这里我就不展示了)

  3.最后总结:①相比于foreach,迭代器iterator的使用略显繁琐;

        ②相比于foreach,迭代器iterato在对数据的操控显然比foreach要灵活。

  最后的最后,上面的总结知识博主自己的个人见解,有不周到的地方,或者错误的地方,请大家指正,谢谢~

时间: 2024-12-06 00:26:06

java容器中遍历循环Iterator 和 Foreach 循环的相关文章

【Java心得总结五】Java容器中——Collection

在[Java心得总结五]Java容器上——容器初探这篇博文中,我对Java容器类库从一个整体的偏向于宏观的角度初步认识了Java容器类库.而在这篇博文中,我想着重对容器类库中的Collection容器做一个着重的探索与总结. Collection:一个独立元素的序列,这些元素都服从一条或多条规则.(注:Collection其实就是将一组数据对象按照一维线性的方式组织起来)List必须按照插入的顺序保存元素,而set不能有重复元素.Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序

为什么阿里巴巴Java开发手册中强制要求不要在foreach循环里进行元素的remove和add操作?

在阅读<阿里巴巴Java开发手册>时,发现有一条关于在 foreach 循环里进行元素的 remove/add 操作的规约,具体内容如下: 错误演示 我们首先在 IDEA 中编写一个在 foreach 循环里进行 remove 操作的代码: import java.util.ArrayList; import java.util.List; public class ForEachTest { public static void main(String[] args) { List<S

java基础40 增强for循环(也叫foreach循环)

增强for循环是jdk1.5出现的新功能 1.增强for循环的作用 简化了迭代器的书写格式(注意:增强for循环底层还是使用了迭代器遍历) 2.增强for循环的格式 for(数据类型 变量名:遍历的目标){ } 3.增强for循环的适用范围 如果实现了 Iterable 接口或者数组对象都可以使用增强for循环 1 package com.dhb.pattern; 2 3 import java.util.Iterator; 4 5 /** 6 * @author DSHORE / 2018-6

13.PHP中循环结构之foreach循环语句(任务一)

在PHP中foreach循环语句,常用于遍历数组,一般有两种使用方式:不取下标.取下标. (1)只取值,不取下标 <?php foreach (数组 as 值){ //执行的任务 } ?> (2)同时取下标和值 <?php foreach (数组 as 下标 => 值){ //执行的任务 } ?> 任务 列出所有学生姓名! 有一组以学号为下标,姓名为值的数组,这时候需要遍历数组的姓名. 1.在右边编辑器中的第16行输入指令: foreach($students as $v)

PHP中循环结构之foreach循环语句

在PHP中foreach循环语句,常用于遍历数组,一般有两种使用方式:不取下标.取下标. (1)只取值,不取下标 <?php foreach (数组 as 值){ //执行的任务 } ?> (2)同时取下标和值 <?php foreach (数组 as 下标 => 值){ //执行的任务 } ?>

java容器中 哪些是线程安全的

容器中线程安全的如:vectory,hashtable,非线程安全的如:hashmap,arrylist等.      对于原定义非线程的容器如:hashmap,arraylist可以使用Collections中的synchronizedList(list),synchronizedMap(map),synchronizedSet(set)等方法来使原来非线程安全的容器编程线程安全. 一.Hashtable 和 Vector 线程安全的容器对象: Vector, Hashtable.线程安全容器

java程序中如何为一个while(true)循环计时,超过一定时间比如10个小时就退出循环?

public void execute(int hour){ long t1 = System.currentTimeMillis(); while(true){ long t2 = System.currentTimeMillis(); if(t2-t1 > hour*60*60*1000){ break; }else{ //TODO your work } } }

JAVA中的for-each循环与迭代

在学习java中的collection时注意到,collection层次的根接口Collection实现了Iterable<T>接口(位于java.lang包中),实现这个接口允许对象成为 "foreach" 语句的目标,而此接口中的唯一方法,实现的就是返回一个在一组 T 类型的元素上进行迭代的迭代器. 一.迭代器Iterator 接口:Iterator<T> 1 public interface Iterator<E>{ 2 3 boolean h

Java中遍历Map的常用方法

以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等): 方式一(推荐): 1 // 推荐 2 // 在for-each循环中使用entries来遍历 3 // 注意:for-each循环在Java 5中被引入所以该方法只能应用于java 5或更高的版本中. 4 // 如果你遍历的是一个空的map对象,for-each循环将抛出NullPointerException,因此在遍历前你总是应该检查空引用. 5 private s