集合(List、Set)遍历和Iterator迭代器

一、Iterator迭代器

1.介绍

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为 “轻量级” 对象,因为创建它的代价小。

Iterator,所有的集合类,都实现了 Iterator 接口(因为Collection 接口继承Iterator接口),这是一个用于遍历集合中元素的接口,并且只能单向移动。主要包含以下三种方法:

  • hasNext () 是否还有下一个元素。
  • next () 返回下一个元素。
  • remove () 删除当前元素。

注意:只有Collection接口继承Iterator接口,而Map接口并没有继承Iterator,所以只有List和Set的实现类实现了Iterator接口的iterator方法,而Map的实现类是无法直接使用iterator方法,之前的章节讲了Map遍历的方式(keyset()和entryset()),是通过返回一个set集合在调用iterator方法的。


2.使用

2.1 对 JAVA 集合进行遍历删除时务必要用迭代器

public static void main(String args[]) {
    List<String> famous = new ArrayList<String>();
    famous.add("liudehua");
    famous.add("madehua");
    famous.add("liushishi");
    famous.add("tangwei");
    for (String s : famous) {
        if (s.equals("madehua")) {
            famous.remove(s);
        }
    }
}

运行出异常:
Exception in thread “main” java.util.ConcurrentModificationException

集合中有两个字段:

  • modCount:集合的修改次数
  • expectedModCount:迭代器对集合进行修改的次数

当两个字段不相同就会报ConcurrentModificationException异常。

如果对正在被迭代的集合进行结构上的改变(即对该集合使用 add、remove 或 clear 方法),那么迭代器就不再合法(并且在其后使用该迭代器将会有 ConcurrentModificationException 异常被抛出).

如果使用迭代器自己的 remove 方法,那么这个迭代器就仍然是合法的:

扫描二维码关注公众号,回复: 8615054 查看本文章
for(Iterator<String> it = famous.iterator();it.hasNext();){
         String s = it.next();
         if(s.equals("madehua")){
             famous.remove(s);
         }
     }

2.2 迭代器的fail-fast和fail-safe属性

每次我们尝试获取下一个元素的时候,Iterator fail-fast 属性检查当前集合结构里的任何改动。如果发现任何改动,它抛出 ConcurrentModificationException。

Iterator 的 fail-fast 属性与当前的集合共同起作用,因此它不会受到集合中任何改动的影响。Java.util 包中的所有集合类都被设计为 fail-fast 的,而 java.util.concurrent 中的集合类都为 fail-safe 的。Fail-fast 迭代器抛出 ConcurrentModificationException,而 fail-safe 迭代器从不抛出 ConcurrentModificationException。

Iterator 接口没有具体的实现,Iterator 接口定义了遍历集合的方法,但它的实现则是集合实现类的责任。每个能够返回用于遍历的 Iterator 的集合类都有它自己的 Iterator 实现内部类。这就允许集合类去选择迭代器是 fail-fast 还是 fail-safe 的。比如,ArrayList 迭代器是 fail-fast 的,而 CopyOnWriteArrayList 迭代器是 fail-safe 的。


二、Iterator和ListIterator 区别

(1)我们可以使用 Iterator 来遍历 Set 和 List 集合,而 ListIterator 只能遍历 List。

(2)Iterator 只可以单向单向遍历,而 LIstIterator 可以双向遍历。

(3)ListIterator 从 Iterator 接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。

发布了147 篇原创文章 · 获赞 835 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/qq_33945246/article/details/103973362
今日推荐