读读源码-ArrayList究竟是怎么实现增强for循环的?

news/2025/2/10 20:42:50/文章来源:https://www.cnblogs.com/kun1790051360/p/18708737

以我的认知来说,java中的ArrayList实现List,List又是继承Collection,往后就不太清楚了。

今天看源码的时候发现Collection继承了Iterable,Iterable接口的作用是允许对象称为for-each loop语句的目标。

因此如果想了解ArrayList如何实现循环,我们必须先从Iterable看起

1.集合之上的接口Iterable

在Iterable中有一个Iterator方法,其他方法,比如foreach都是有default,暂时先不用看

public interface Iterable<T> {Iterator<T> iterator();default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}default Spliterator<T> spliterator() {return Spliterators.spliteratorUnknownSize(iterator(), 0);}
}

在Iterator接口中也有两个需要实现的方法

boolean hasNext()和T next()通过名字我们就知道这两个方法是检测当前循环里有没有下一个数据以及下一个数据的返回。

2.增强for语句的真面貌

    //正常使用的增强for方法public static void enhanceFor(ArrayList<String> list){for (String s : list) {System.out.println(s);}}
   //编译后的class文件 public static void enhanceFor(ArrayList<String> list) {Iterator var1 = list.iterator();while(var1.hasNext()) {String s = (String)var1.next();System.out.println(s);}}

可以看到,增强的for方法实际就是使用的迭代器内的方法实现的循环遍历

3.ArrayList中的Iterable

那么实际在ArrayList中,是如何实现的Iterable与Iterator呢?、

Iterator中只写了返回一个对象,通过原接口我们知道这个对象就是Iterator

    public Iterator<E> iterator() {return new Itr();}

 

    private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;Itr() {}public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}}

这里我们只看hasNext和next方法

hasNext中,只要游标cursor不等于size就返回true,也就是说明后面还有数据

next方法中,首先是checkForComodification方法,可以看到是在检测modCount和expectedModCount是否相等

        final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}

 通过解释我们知道,在正常的循环的时候modCount和expectedModCount是应该被指定好且相同的、

但是如果我们在循环中改变了循环体,那会导致两者参数不一致进而出现迭代产生错误结果,为此抛出了这段异常。

后续就是检测越界问题,没问题的话就给游标加一保证迭代并将集合中获得的元素返回。

4.让自定义类也能实现for循环

读过上述源码后,我们就知道如何给一个自定义类实现增强for循环了

@Data
@ToString
public class User implements Iterable {String name;Integer age;Boolean sex;@NotNull@Overridepublic Iterator iterator() {return new Itr();}class Itr implements Iterator<String> {private final int max = 3;private int cursor = 0;@Overridepublic boolean hasNext() {return cursor < max;}@Overridepublic String next() {return switch (cursor++) {case 0 -> name != null ? name : "null";case 1 -> age != null ? age.toString() : "null";case 2 -> sex != null ? sex.toString() : "null";default -> throw new NoSuchElementException();};}}
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“此电脑”不是“我的电脑”怎么办

在以前,我们可以按住win+E就可以打开到有盘符的界面(直接看见C盘,D盘,E盘……),现在win11没有这个效果了,我还得再在左边的选项里寻找“此电脑”再进入我想要的“我的电脑”界面,真麻烦!无缘无故多了几个点击步骤,效率真低! 今天,我想改变这个效果!自已自足!。。…

香港海底光缆-转载2020

转自:http://live.xiaohongshu.com.sdwan.ltd/index.php?m=home&c=View&a=index&aid=132香港作为全球重要数据传输驿站之一,其网络传输能力自然不可小瞧。根据香港政府通讯事务管理局办公室给出的资料,截至2019年1月,香港有十一个海缆系统,即亚非欧1号光缆系…

miniconda安装和配置

第一步,下载和安装访问Download Anaconda Distribution | Anaconda,跳过注册"Skip registration",进入下载界面往下拉,选择miniconda的下载。安装时候注意勾选PATH路径的配置选项。第二步,安装完成后通过Anaconda Prompt打开命令行,看到提示符前面有(base)字…

智能化物资安全管理:AI视频监控在大型商场的技术方案介绍(part3)

项目背景:商场在运营中面临商品失窃的风险,需要通过技术手段实时预防偷窃行为,保护物资安全。 一、具体需求: 1、姿势与行为异常识别:检测顾客的异常行为,例如夹带物品、将商品从货架放入包中等动作。 2、异常行为检测:监控顾客长时间逗留、异常交互(如反复拿取同一物品…

JAVA之面向对象进阶

1、staticstatic表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量。被static修饰的成员变量,叫做静态变量【特点:1.被该类所有对象共享 2.不属于对象,属于类 3.随着类的加载而加载,优先于对象存在 调用方式:1、类名调用(推荐) 2、对象名调用】 被static修饰…

小红书开源 FireRedASR 语音识别模型,3.05% 字错误率;Meta AI 脑电波打字模型:32% 字错误率

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑…

008 对象的扩展

1、属性的简洁表示法ES6允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。let name ="iwen"const user={name,age:20} 除了属性简写,方法也可以简写const o ={method(){return"hello!";}}; //等同于 const o={method:f…

python uv stands for what?

python uv stands for what?uv 是 Python 生态中一个新兴的高性能工具,由 Rust 编写,旨在替代传统的 pip 和 venv。它由 Charlie Marsh(知名工具 Ruff 的开发者)主导开发,核心目标是解决 Python 包管理的速度和效率问题。 核心功能极速安装:比 pip 快 10-100 倍,依赖解…

构建智能汽车地图标准体系:自动驾驶技术的基石

随着智能汽车技术的快速发展,基础地图作为智能汽车不可或缺的组成部分,其标准化建设显得尤为重要。本文将探讨智能汽车基础地图标准体系的构建以及关键技术的研究进展。智能汽车基础地图的重要性智能汽车基础地图,也称为自动驾驶地图或高精地图,不仅包含静态地图信息,还涵…

【qt】切页控件

//切换方向enum class switchDirection{Horizontal, //水平Vertical //垂直};//动画模式enum class aniMode{Switch, //切换Cover //覆盖};//设置动画持续的间隔void setDuration(int ms);//设定动画模式void setAniMode(aniMode mode);aniMode getAniMode();//设定切页…

14. IO文件操作

一、为什么要使用文件我们之前写的程序在运行起来的时候,我们可以给程序增加或删除数据,此时的数据都是存在内存中。当程序执行完毕退出的时候,之前程序中增减或减少的数据就不存在了,等程序下一个运行的时候,数据又会重新录入。如果我们想把程序中的数据记录来,只有在我…

AI 重塑宗教体验,语音 Agent 能否成为突破点?

基于语音 AI 和 Voice Agent 的视角,推荐「硅谷科技评论」这篇关于宗教技术(FaithTech)与 AI 融合的深度分析,理由如下:1. 语音场景契合: 宗教及冥想类应用是典型的「解放双手」(handfree)(用户倾向于非屏幕交互)和深度情感连接的场景,天然适合语音及声音交互。2. L…