Java进阶篇--迭代器模式

这篇具有很好参考价值的文章主要介绍了Java进阶篇--迭代器模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

同步迭代器(Synchronous Iterator):

Iterator 接口

常用方法:

注意:

扩展小知识:

异步迭代器(Asynchronous Iterator):

常用的方法

注意:

总结:

代码示例

示例一:

示例二:

示例三:


在Java中,可以根据迭代器的行为模式将其分为同步迭代器(Synchronous Iterator)和异步迭代器(Asynchronous Iterator)。它们是两种不同的迭代器模式,用于在遍历集合或序列时提供不同的行为方式。

同步迭代器(Synchronous Iterator):

同步迭代器是一种阻塞式的迭代器,它在处理当前元素时会等待操作完成后再返回下一个元素。在使用同步迭代器进行遍历时,每次调用next()方法,迭代器会检查当前元素是否已完成处理。如果当前元素仍在处理中,迭代器将阻塞等待,直到操作完成并返回下一个元素。

同步迭代器的优点是可以保证遍历顺序的正确性,因为每次只返回一个元素,并且等待前一个元素处理完成后才返回下一个元素。这在单线程环境或需要确保遍历顺序的场景中非常有用。Java标准库中的 Iterator 接口就是一种同步迭代器。

Iterator 接口

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,Java专门提供了一个接口Iterator。Iterator接口也是集合中的一员,但它与Collection、Map接口有所不同。Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例演示Iterator对象迭代元素的过程。

Java进阶篇--迭代器模式,Java进阶篇,迭代器模式,java,开发语言

上图中,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next()方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next()方法时,迭代器的索引会指向第二个元素并将该元素返回,以此类推,直到hasNext()方法返回false,表示到达了集合的末尾,终止对元素的遍历。

常用方法:

  1. boolean hasNext(): 判断集合中是否还有下一个元素,如果有则返回true,否则返回false。
  2. E next(): 返回迭代器中的下一个元素,并将迭代器的指针向后移动一位。如果没有下一个元素,则抛出NoSuchElementException异常。
  3. void remove(): 从集合中删除迭代器最后一次返回的元素。注意,该方法只能在调用next方法之后且尚未再次调用remove方法时才能调用。如果在调用remove方法之前没有调用过next方法,或者在上一次调用next方法之后又调用了remove方法,则会抛出IllegalStateException异常。

Iterator接口提供了基本的遍历功能,可以通过循环结构配合使用hasNext和next方法来遍历集合中的元素。同时,可以使用remove方法在遍历过程中删除特定元素。

注意:

  1. 通过迭代器获取ArrayList集合中的元素时,这些元素的类型都是Object类型,如果想获取到特定类型的元素,则需要进行对数据类型强制转换。
  2. 在使用Iterator迭代集合时,避免直接在迭代期间修改集合结构,以免触发ConcurrentModificationException异常。

扩展小知识:

ConcurrentModificationException异常表示在迭代器运行期间,通过集合对象对集合进行了结构性修改(如添加或删除元素),导致迭代器的预期迭代次数与实际迭代次数不一致,从而抛出异常。

这个异常通常发生在使用普通的Iterator进行迭代时,而不是使用并发安全的迭代器(如ConcurrentHashMap的迭代器)。当你使用普通的Iterator进行迭代时,是不能在迭代过程中直接对集合进行结构性修改的,否则就会触发ConcurrentModificationException异常。

解决此异常的方法有两种:

  1. 使用Iterator的remove()方法:可以在迭代过程中调用Iterator的remove()方法来删除元素,它是唯一能够在迭代期间安全删除元素的方法。示例代码如下:
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String element = iterator.next();
        if (condition to remove element) {
            iterator.remove(); // 删除当前元素,不会抛出异常
        }
    }
    
  2. 使用并发安全的集合类:如果需要在迭代期间对集合进行修改操作,可以考虑使用并发安全的集合类,如CopyOnWriteArrayList、ConcurrentHashMap等。这些集合类提供了迭代器的安全性,并且允许在迭代期间进行修改操作。

所以,在使用Iterator迭代集合时,避免直接在迭代期间修改集合结构,以免触发ConcurrentModificationException异常。如果需要修改集合,请使用Iterator的remove()方法或并发安全的集合类来确保迭代器的正确性。

异步迭代器(Asynchronous Iterator):

异步迭代器是一种非阻塞式的迭代器,它在处理当前元素时不会等待操作完成而立即返回下一个元素。异步迭代器通常采用回调函数、事件通知或其他机制来进行处理结果的通知。

在使用异步迭代器进行遍历时,调用next()方法会立即返回下一个元素,并且可能会触发异步处理操作。迭代器会在后台或其他线程中进行元素的处理,当处理完成时,通过回调函数或事件通知机制将结果通知给使用者。

异步迭代器的优点是可以提高遍历效率和并发性能,因为它不需要等待当前元素的处理完成。这在多线程环境、异步编程或需要处理耗时操作的场景中非常有用。

常用的方法

  1. next(): 获取异步迭代器的下一个元素。此方法会返回一个CompletableFuture对象,我们可以通过该对象来获取异步操作的结果。
  2. hasNext(): 判断异步迭代器是否还有下一个元素。返回一个CompletableFuture<Boolean>对象,用于表示是否存在下一个元素。
  3. forEachRemaining(action): 对剩余的元素执行给定的操作,直到所有元素都已处理完毕或遇到异常。
  4. tryAdvance(action): 尝试对下一个元素执行给定的操作。如果存在下一个元素,则对其执行操作并返回true,否则返回false。
  5. close(): 关闭异步迭代器,释放相关资源。在使用完异步迭代器后,应该及时调用该方法以避免资源泄露。

注意:

同步迭代器和异步迭代器的选择要根据具体的需求和场景来决定。同步迭代器适合保证遍历顺序和单线程环境,而异步迭代器适合提高遍历效率和并发性能,但可能需要额外的异步处理机制。

总结:

同步迭代器是阻塞式的,等待当前元素处理完成后再返回下一个元素;异步迭代器是非阻塞式的,在处理当前元素时不等待操作完成而立即返回下一个元素,并通过回调或事件通知机制进行结果通知。在Java中,常见的迭代器是同步迭代器,但可以根据需要自定义或使用第三方库实现异步迭代器的功能。

代码示例

示例一:

同步迭代器代码示例(使用Iterator接口):

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

public class Main {
    public static void main(String[] args) {
        // 创建一个空的列表
        List<String> list = new ArrayList<>();
        // 添加元素到列表
        list.add("Apple");
        list.add("Banana");
        list.add("Orange");
        // 获取集合的迭代器
        Iterator<String> iterator = list.iterator();

        // 循环遍历集合中的元素
        while (iterator.hasNext()) {
            // 获取下一个元素并移动迭代器指针
            String element = iterator.next();
            System.out.println(element);
        }
    }
}

示例二:

异步迭代器代码示例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

// 自定义异步迭代器接口
interface AsyncIterator<T> {
    CompletableFuture<Boolean> hasNext(); // 异步判断是否存在下一个元素
    CompletableFuture<T> next(); // 异步获取下一个元素
    void close(); // 关闭迭代器,释放资源
}

// 异步迭代器实现类
class SimpleAsyncIterator<T> implements AsyncIterator<T> {
    private final T[] elements; // 数据序列
    private int currentIndex; // 当前索引

    public SimpleAsyncIterator(T[] elements) {
        this.elements = elements;
        this.currentIndex = 0;
    }

    @Override
    public CompletableFuture<Boolean> hasNext() {
        return CompletableFuture.completedFuture(currentIndex < elements.length); // 完成时返回是否还有下一个元素的结果
    }

    @Override
    public CompletableFuture<T> next() {
        T element = elements[currentIndex]; // 获取当前元素
        currentIndex++; // 索引自增
        return CompletableFuture.completedFuture(element); // 完成时返回当前元素
    }

    @Override
    public void close() {
        // 可以在此释放相关资源
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建数据序列
        Integer[] numbers = {1, 2, 3, 4, 5};

        // 创建异步迭代器
        AsyncIterator<Integer> iterator = new SimpleAsyncIterator<>(numbers);

        // 创建线程池
        Executor executor = Executors.newFixedThreadPool(2);

        // 异步遍历和处理数据序列
        CompletableFuture.runAsync(() -> {
            while (true) {
                CompletableFuture<Boolean> hasNextFuture = iterator.hasNext();

                // 异步获取是否存在下一个元素
                hasNextFuture.thenCompose(hasNext -> {
                    if (hasNext) {
                        // 异步获取下一个元素并处理
                        CompletableFuture<Integer> nextFuture = iterator.next();
                        nextFuture.thenAcceptAsync(Main::processData, executor);
                    } else {
                        // 处理完所有元素后关闭迭代器
                        iterator.close();
                    }
                    return CompletableFuture.completedFuture(null);
                }).join(); // 阻塞等待完成
            }
        }, executor);
    }

    // 数据处理方法示例
    private static void processData(Integer data) {
        System.out.println("正在处理数据: " + data);
        // 具体的数据处理逻辑
    }
}

示例三:

综合同步迭代器和异步迭代器代码示例:文章来源地址https://www.toymoban.com/news/detail-656942.html

import java.util.Iterator;
import java.util.NoSuchElementException;

// 同步迭代器
class SynchronousIterator implements Iterator<Integer> {
    private int[] array;    // 存储数据的数组
    private int index;      // 当前迭代位置

    public SynchronousIterator(int[] array) {
        this.array = array;
        this.index = 0;
    }

    // 检查是否还有下一个元素
    @Override
    public boolean hasNext() {
        return index < array.length;    // 当前位置是否小于数组长度
    }

    // 返回下一个元素,并将迭代器指针向后移动一位
    @Override
    public Integer next() {
        if (hasNext()) {                // 如果还有下一个元素
            int element = array[index]; // 获取当前位置的元素
            index++;                    // 将迭代器指针向后移动一位
            return element;             // 返回当前元素
        }
        throw new NoSuchElementException();   // 抛出异常表示没有下一个元素
    }
}

// 异步迭代器
class AsynchronousIterator implements Iterator<Integer> {
    private int[] array;    // 存储数据的数组
    private int index;      // 当前迭代位置

    public AsynchronousIterator(int[] array) {
        this.array = array;
        this.index = 0;
    }

    // 检查是否还有下一个元素
    @Override
    public boolean hasNext() {
        // 在此处可以进行异步操作,例如请求远程数据或执行耗时任务
        // 返回 true 表示还有元素,返回 false 表示迭代结束
        return index < array.length;    // 当前位置是否小于数组长度
    }

    // 返回下一个元素,并将迭代器指针向后移动一位
    @Override
    public Integer next() {
        if (hasNext()) {                // 如果还有下一个元素
            int element = array[index]; // 获取当前位置的元素
            index++;                    // 将迭代器指针向后移动一位
            return element;             // 返回当前元素
        }
        throw new NoSuchElementException();   // 抛出异常表示没有下一个元素
    }
}

// 示例用法
public class Main {
    public static void main(String[] args) {
        int[] numbers = { 1, 2, 3, 4, 5 };   // 定义一个整数数组作为数据源

        // 同步迭代器示例
        Iterator<Integer> syncIterator = new SynchronousIterator(numbers);
        while (syncIterator.hasNext()) {         // 遍历迭代器中的元素
            Integer number = syncIterator.next(); // 获取当前元素
            System.out.println(number);           // 输出当前元素
        }

        // 异步迭代器示例
        Iterator<Integer> asyncIterator = new AsynchronousIterator(numbers);
        while (asyncIterator.hasNext()) {         // 遍历迭代器中的元素
            Integer number = asyncIterator.next(); // 获取当前元素
            System.out.println(number);            // 输出当前元素
        }
    }
}

到了这里,关于Java进阶篇--迭代器模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java 设计者模式以及与Spring关系(七) 命令和迭代器模式

    本文是个系列一次会出两个设计者模式作用,如果有关联就三个,除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道 设计者模式 有 3 类 23 种设计模式,标红是特别重要的设计者模式建议都会,而且熟读于心,标蓝是指其次重要建议也要明白。 (1)创建

    2024年01月24日
    浏览(34)
  • 使用迭代方式解决汉诺塔问题(Java语言)

    目录 汉诺塔问题解决 迭代介绍         在这个Java示例中,我们使用了一个 Stack 数据结构来模拟递归调用的过程。 hanoiIterative 函数接受盘子数量 n 以及三个柱子的名称作为参数,并在迭代过程中模拟汉诺塔的移动操作。 moveDisk 函数用于模拟盘子的移动操作。        

    2024年02月09日
    浏览(49)
  • 【设计模式——学习笔记】23种设计模式——迭代器模式Iterator(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    编写程序展示一个学校院系结构: 需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系 【传统方式】 将学院看做是学校的子类,系是学院的子类,小的组织继承大的组织 分析: 在一个页面中展示出学校的院系组成,一个学校有多个

    2024年02月14日
    浏览(39)
  • java使用策略模式(进阶篇)

    策略模式是一个非常简单且常用的设计模式,策略模式最常见的作用就是解决代码中冗长的 if-else 或 switch 分支判断语句。 本文后半部分应该会让熟悉策略模式的同学也会有一些收获。本文重点在于笔者阅读 Flink 源码过程中发现了一个设计比较巧妙的点,可以对策略模式进行

    2024年02月01日
    浏览(49)
  • 🔥🔥Java开发者的Python快速进修指南:迭代器(Iterator)与生成器

    这一篇内容可能相对较少,但是迭代器在Java中是有用处的。因此,我想介绍一下Python中迭代器的使用方法。除了写法简单之外,Python的迭代器还有一个最大的不同之处,就是无法直接判断是否还有下一个元素。我们只能通过捕获异常或使用for循环来退出迭代,这点让我感到十

    2024年02月05日
    浏览(51)
  • 【Java 进阶篇】Java Web开发:实现验证码功能

    在Web应用程序中,验证码(CAPTCHA)是一种常见的安全工具,用于验证用户是否为人类而不是机器。验证码通常以图像形式呈现,要求用户在登录或注册时输入正确的字符。在这篇文章中,我们将详细介绍如何在Java Web应用程序中实现验证码功能。 验证码是“全自动区分计算机

    2024年02月03日
    浏览(38)
  • Java 基础进阶篇(一)——— static 静态关键字与单例模式

    static:代表静态的意思,可以修饰成员变量,可以修饰成员方法。 static 修饰方法之后称为 静态方法(类方法) ,修饰成员变量之后称为 静态成员变量(类变量) 。 static 修饰后的成员变量, 可以被类的所有对象共享 (访问、修改) 。 静态成员变量 实例成员变量 概述 有

    2024年02月01日
    浏览(84)
  • 🔥🔥Java开发者的Python快速进修指南:函数进阶

    在上一篇文章中,我们讲解了函数最基础常见的用法,今天我想在这里简单地谈一下函数的其他用法。尽管这些用法可能不是非常常见,但我认为它们仍然值得介绍。因此,我将单独为它们开设一个章节,并探讨匿名函数和装饰器函数这两种特殊的用法。 在Python中,匿名函数

    2024年02月05日
    浏览(55)
  • 🔥🔥Java开发者的Python快速进修指南:面向对象进阶

    在上一期中,我们对Python中的对象声明进行了初步介绍。这一期,我们将深入探讨对象继承、组合以及多态这三个核心概念。不过,这里不打算赘述太多理论,因为我们都知道,Python与Java在这些方面的主要区别主要体现在语法上。例如,Python支持多重继承,这意味着一个类可

    2024年02月05日
    浏览(59)
  • 【进阶篇】Java 实际开发中积累的几个小技巧(二)

    目录 前言 六、自定义注解 6.1定义注解 6.2切面实现 6.3业务使用 七、抽象类和接口 7.1隔离业务层与 ORM 层 7.2隔离子系统的业务实现 7.3选择对比 文章小结 笔者目前从事一线 Java 开发今年是第 3 个年头了,从 0-1 的 SaaS、PaaS 的项目做过,基于多租户的标准化开发项目也做过,项

    2024年04月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包