Java编程语言,使用迭代器Iterator实现自动分页查询

news2024/11/19 20:30:30

一、背景

在Java中,Iterator是一种设计模式,用于提供一种按顺序访问集合中元素的方式,而不暴露集合的底层表示。Iterator接口主要用于遍历集合,它定义了两种方法:hasNext()和next()。

借助于迭代器Iterator,可以逐页迭代API返回的数据,而不需要用户手动处理分页逻辑。

二、迭代器Iterator

迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。

  • hasNext()
    目的:hasNext()方法用来检测迭代器是否还有下一个元素可以迭代。
    返回值:返回一个布尔值,如果存在下一个元素则返回true,否则返回false。
    使用场景:在调用next()方法之前使用hasNext()可以避免发生NoSuchElementException。
  • next()
    目的:next()方法用来获取迭代器当前指向的下一个元素。
    返回值:返回迭代器中的下一个元素。
    异常:如果没有下一个元素,即在hasNext()返回false的情况下调用next(),将抛出NoSuchElementException。
  • 示例用法
Iterator<String> iterator = someCollection.iterator();
while(iterator.hasNext()) {
    String element = iterator.next();
    // 对element进行操作
}

三、自动分页查询

下图是一个迭代器的框架

在这里插入图片描述

1、遍历每页,直到下一页的数据为空

因为查询是通用的功能,所以这里使用的是泛型,而非具体类。

    public <T> List<T> getAll(final String url, final Class<T[]> type) {
        List<T> results = new ArrayList<>();
        Iterator<T[]> iterator = asIterator(url, type);

        while (iterator.hasNext()) {
            T[] requests = iterator.next();

            if (requests.length > 0) {
                results.addAll(Arrays.asList(requests));
            }
        }
        return results;
    }

2、实现迭代器

  • 有两个成员变量:next(下一个要返回的对象)和url(当前要请求的URL)
  • hasNext(),先调用fetch()方法来获取下一个数据,当返回的数组类型,则要求数组的长度大于0;否则next对象必须非空。
  • next(),它先调用fetch()来确保next已经被赋值,返回next,并将next重置为null。所以,本方法额外使用了一个变量record,用来存储本次查询返回值。- - 不能直接使用next对象。
   public <T> Iterator<T> asIterator(final String requestUrl, final Class<T> type) {
        return new Iterator<T>() {
            T next;
            URL url = new URL(requestUrl);

            @Override
            public boolean hasNext() {
                fetch();
                if (next != null && next.getClass().isArray()) {
                    Object[] arr = (Object[]) next;
                    return arr.length != 0;
                } else {
                    return next != null;
                }
            }

            @Override
            public T next() {
                fetch();
                T record = next;

                if (record == null) {
                    throw new NoSuchElementException();
                }

                next = null;
                return record;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
  • fetch()方法,它会对next进行赋值,如果已有值,则返回。同时,它会组装好查询下一页的请求url。
			private void fetch() {
                if (next != null) {
                    return;
                }

                if (url == null) {
                    return;
                }

                try {
                    try {
                        next = query(url, type);
                        assert next != null;
                        findNextUrl();
                    } catch (IOException e) {
                        handleAPIError(e, connection);
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            }
  • findNextUrl(),组装下一页的请求url。使用了正则表达式PAGE_PATTERN来查找和替换URL中的分页页码,即参数page。
private static final Pattern PAGE_PATTERN = Pattern.compile("([&|?])page=(\\d+)");

			private void findNextUrl() throws MalformedURLException {
                String url = this.url.toString();

                this.url = null;
                /* Increment the page number for the url if a "page" property exists,
                 * otherwise, add the page property and increment it.
                 * The Gitlab API is not a compliant hypermedia REST api, so we use
                 * a naive implementation.
                 */
                Matcher matcher = PAGE_PATTERN.matcher(url);

                if (matcher.find()) {
                    Integer page = Integer.parseInt(matcher.group(2)) + 1;
                    this.url = new URL(matcher.replaceAll(matcher.group(1) + "page=" + page));
                } else {
                    // Since the page query was not present, its safe to assume that we just
                    // currently used the first page, so we can default to page 2
                    this.url = new URL(url + (url.indexOf('?') > 0 ? '&' : '?') + "page=2");
                }
            }

四、另一种分页查询的实现

使用spring 的 Pageable逐页查询,Jpa的实现示例见下:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

Page<Course> findByModifiedDateGreaterThanEqualAndModifiedDateLessThanEqual(Date startDate, Date endDate, Pageable request);

和迭代器Iterator的实现类似,这里使用do…while循环,利用next()方法一直往后查询,直到记录为空。

    private void sync(Date lastSyncDate, Date thisSyncDate) {
        Page<Course> coursePage;

        Pageable page = PageRequest.of(0, 100, Sort.Direction.ASC, "modifiedDate");
        do {
            coursePage = courseRepository.findByModifiedDateGreaterThanEqualAndModifiedDateLessThanEqual(
                    lastSyncDate,
                    thisSyncDate,
                    page);
            List<Course> list = coursePage.getContent();
            page = page.next();
        } while (!coursePage.isEmpty());
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1683283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp-自定义navigationBar

封装导航栏自定义组件 创建 nav-bar.vue <script setup>import {onReady} from dcloudio/uni-appimport {ref} from vue;const propsdefineProps([navBackgroundColor])const statusBarHeight ref()const navHeight ref()onReady(() > {uni.getSystemInfo({success…

modbus开源库libmodbus的C语言使用记录(实现简单的modbus主机/丛机程序,解决libmodbus库安装出现的问题)

libmodbus简介 libmodbus 是一个开源的、跨平台的C库,用于实现Modbus通讯协议。它支持Modbus RTU(RS-232/485)和Modbus TCP协议,可以使开发者方便地在项目中集成Modbus通讯功能。libmodbus的设计目标是简单、灵活和高效,适用于各种大小的嵌入式和桌面应用。 编译运行测试…

交换机连接方式

一、级联方式 级联是将多个交换机或其他网络设备依次连接&#xff0c;形成一个层次结构&#xff0c;从而扩展网络的覆盖范围和端口数量。 在级联连接中&#xff0c;数据信号会从一个设备依次传递到下一个设备。每个设备都会接收并处理来自上级设备的数据&#xff0c;并将其转…

vb.net打开CAD指指定路径文件

首先打开vsto,创建窗体&#xff0c;添加一个按钮&#xff0c;双击按钮录入代码&#xff1a; Public Class Form1Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.ClickDim cad As Objectcad CreateObject("autocad.Application")cad…

Spring Cloud整合Sentinel

1、引入依赖 链接: 点击查看依赖关系 父pom <spring.cloud.version>Hoxton.SR12</spring.cloud.version> <spring.cloud.alibaba.version>2.2.10-RC1</spring.cloud.alibaba.version>Sentinel应用直接引用starter <dependency><groupId&…

《2024中国AI大模型产业图谱1.0版》重磅发布

‍ 数据猿出品 本次“数据猿2024年度三大媒体策划活动——《2024中国数据智能产业图谱1.0版》”正式发布。下一次版本迭代将于2024年7月底发布2024年2.0版&#xff0c;敬请期待&#xff0c;欢迎报名。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着科技的飞速发展&#…

三维焊接平台在新一代机器人生产中得到广泛应用-河北北重

随着智能制造行业的不断推进&#xff0c;三维焊接平台在工业机器人领域应用现象普遍。三维焊接平台、三维柔性焊接平台工装夹具也会在新一代机器人——智能机器人在工业生产中得到广泛应用。目前&#xff0c;三维焊接平台、焊接铸铁平台在工业机器人的主要作用是应用于弧焊、电…

202472读书笔记|《首先你要快乐,其次都是其次》——快乐至上,允许一切发生

202472读书笔记|《首先你要快乐&#xff0c;其次都是其次》——快乐至上&#xff0c;允许一切发生 《首先你要快乐&#xff0c;其次都是其次》作者林小仙&#xff0c;挺轻松的小漫画&#xff0c;清新的文字。 生而为人&#xff0c;我很抱歉&#xff0c;大可不必。 生活已经很难…

鸿蒙HarmonyOS开发中的易混点归纳-持续补充中

相关文章目录 鸿蒙HarmonyOS开发术语全解&#xff1a;小白也能看懂&#xff01; 文章目录 相关文章目录前言一、build()函数和Builder装饰器&#xff1f;二、自定义组件和系统组件&#xff08;内置组件&#xff09;三、组件和页面四、自定义弹窗和其他弹窗总结 前言 一、build…

【BSP开发经验】简易文件系统digicapfs实现方式

文章目录 背景Linux vfs框架介绍数据结构系统调用openwriteread 总体框架 Linux 磁盘高速缓存机制标准文件访问同步文件访问异步文件访问buffer_head 如何实现一个简单的文件系统blkdevfs注册文件系统产生一个文件让文件变得可读可写 背景 在新的分区升级启动方案中需要分别实…

《QT实用小工具·六十五》基于QPropertyAnimation实现的移动动画和控件覆盖

1、概述 源码放在文章末尾 该项目基于QPropertyAnimation实现了控件平移动画和控件之间的相互覆盖效果&#xff0c;项目demo演示如下所示&#xff1a; 项目解析&#xff1a; new QPropertyAnimation(ui.SingleOcclusion, “pos”); //创建动画对象&#xff0c;第一个参数传…

什么是流量削峰?如何解决秒杀等业务的削峰场景

文章推荐 1 作为程序员&#xff0c;开发用过最好用的AI工具有哪些&#xff1f; 2 Github Copilot正版的激活成功&#xff0c;终于可以chat了 3 idea,pycharm等的ai assistant已成功激活 4 新手如何拿捏 Github Copilot AI助手&#xff0c;帮助你提高写代码效率 5 Jetbrains的a…

ROS | 自定义发布地图

C代码&#xff1a; Step: Python代码:

202212青少年软件编程(Python) 等级考试试卷(三级)

第1题:【 单选题】 列表 L1 中全是整数,小明想将其中所有奇数都增加 1,偶数不变,于是编写了如下图所示的代码。 请问,图中红线处,代码应该是? ( ) A:x || 2 B:x^2 C:x&&2 D:x%2 【正确答案】: D 【试题解析】 : 本题代码中, for x in L1 是在 L1 列表中循…

关于如何创建一个可配置的 SpringBoot Web 项目的全局异常处理

前情概要 这个问题其实困扰了我一周时间&#xff0c;一周都在 Google 上旅游&#xff0c;我要如何动态的设置 RestControllerAdvice 里面的 basePackages 以及 baseClasses 的值呢&#xff1f;经过一周的时间寻求无果之后打算决定放弃的我终于找到了一些关键的线索。 当然在此…

鸿蒙 DevEcoStudio:通知栏通知实现

【使用notificationManager实现通知栏功能】 【普通通知、长文本通知、多行通知、图片通知】 import notificationManager from ohos.notificationManager import image from ohos.multimedia.image Entry Component struct Index {State message: string Hello World// 将图…

网络安全之BGP详解

BGP&#xff1b;边界网关协议 使用范围&#xff1b;BGP范围&#xff0c;在AS之间使用的协议。 协议的特点&#xff08;算法&#xff09;&#xff1a;路径矢量型&#xff0c;没有算法。 协议是否传递网络掩码&#xff1a;传递网络掩码&#xff0c;支持VLSM&#xff0c;CIDR …

17款奔驰GLS450升级头等舱行政独立四座马鞍是什么样体验

五座版本&#xff1a;迈巴赫GLS480的五座版本通常指的是具有五个座位的配置&#xff0c;包括两个前排座椅和三个后排座椅。这种配置适合搭载更多乘客&#xff0c;后排座椅通常为三人座设计&#xff0c;乘坐人数较多。 四座版本&#xff1a;迈巴赫GLS480的四座版本通常指的是具…

基于地理坐标的高阶几何编辑工具算法(4)——线分割面

文章目录 工具步骤应用场景算法输入算法输出算法示意图算法原理 工具步骤 选中待分割面&#xff0c;点击“线分割面”工具&#xff0c;绘制和面至少两个交点的线&#xff0c;双击结束&#xff0c;执行分割操作 应用场景 快速切分大型几何面&#xff0c;以降低面的复杂度&…

云曦2024年春季学期期中考复现

目录 Web Web_SINGIN 简简单单的文件上传 好玩的PHP 渗透的本质 简简单单的sql re baby_re easy xor Crypto easy_rsa Rsa2 Crypto_Singin Pwn pwn_Sing Misc easy_singin Xjpg 流量分析1 流量分析3 流量分析2 Web Web_SINGIN 1.使用右键检查&#xff0c…