阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

迭代器笔试题,看看你会不会?

262次阅读
没有评论

共计 3791 个字符,预计需要花费 10 分钟才能阅读完成。

导读 有位小朋友最近正在为年后换工作做准备,但是遇到一个问题,觉得很不可思议的一道笔试题。然后我把这道题发到技术群里,发现很多人居然不知道,很多都是连蒙带猜的说。感觉很有必要写一篇文章来说道说道。

有位小朋友最近正在为年后换工作做准备,但是遇到一个问题,觉得很不可思议的一道笔试题。然后我把这道题发到技术群里,发现很多人居然不知道,很多都是连蒙带猜的说。感觉很有必要写一篇文章来说道说道。
迭代器笔试题,看看你会不会?

迭代器笔试题,看看你会不会?
奇怪的笔试题阅读下面这段代码,请写出这段代码的输出内容:

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.*; 
 
public class Test {public static void main(String[] args) {List list = new ArrayList(); 
        list.add("1"); 
        list.add("2"); 
        list.add("3"); 
        Iterator iterator = list.iterator(); 
        while (iterator.hasNext()) {String str = (String) iterator.next(); 
            if (str.equals("2")) {iterator.remove(); 
            } 
        } 
        while (iterator.hasNext()) {System.out.println(iterator.next()); 
        } 
        System.out.println("4"); 
    } 
} 

他写出来的答案是:

1 
3 
4

奇怪的是,你把这道题目发给你身边人,让他们回答这道面试题输出结果是什么,说这个结果的人非常多。不行你试试。

答案明显不对,因为在第一个 while 里的 iterator.hasNext()==false 后才会到第二个 while 里来,同一个 Iterator 对象,前面调一次 iterator.hasNext()==false,再判断一次结果不还是一样吗?,

所以第二个 while 判断为 false,也就不会再去遍历 iterator 了,由此可知本体答案是:4。

下面我们来分析一下为什么是具体底层是怎么实现的。

这里的 Iterator 是什么?

迭代器是一种模式、详细可见其设计模式,可以使得序列类型的数据结构的遍历行为与被遍历的对象分离,即我们无需关心该序列的底层结构是什么样子的。只要拿到这个对象, 使用迭代器就可以遍历这个对象的内部
Iterable 实现这个接口的集合对象支持迭代,是可以迭代的。实现了这个可以配合 foreach 使用~
Iterator 迭代器,提供迭代机制的对象,具体如何迭代是这个 Iterator 接口规范的。
Iterator 说明

public interface Iterator {  
    // 每次 next 之前,先调用此方法探测是否迭代到终点 
    boolean hasNext(); 
    // 返回当前迭代元素,同时,迭代游标后移 
    E next();  
    /* 删除最近一次已近迭代出出去的那个元素。只有当 next 执行完后,才能调用 remove 函数。比如你要删除第一个元素,不能直接调用 remove()   而要先 next 一下(); 
     在没有先调用 next 就调用 remove 方法是会抛出异常的。这个和 MySQL 中的 ResultSet 很类似 
    */ 
    default void remove() {throw new UnsupportedOperationException("remove"); 
    }  
    default void forEachRemaining(Consumer super E> action) {Objects.requireNonNull(action); 
        while (hasNext()) 
            action.accept(next()); 
    } 
} 

这里的实现类是 ArrayList 的内部类 Itr。

private class Itr implements Iterator { 
        int cursor;       // index of next element to return 
        int lastRet = -1; // index of last element returned; -1 if no such 
        //modCountshi ArrayList 中的属性,当添加或删除的时候 moCount 值会增加或者减少 
        // 这里主要是给 fail-fast 使用,避免一遍在遍历,一遍正在修改导致数据出错 
        // 此列表在结构上被修改的次数。结构修改是指改变结构尺寸的修改列表,// 或者以这样的方式对其进行扰动, 进步可能会产生错误的结果。int expectedModCount = modCount; 
         
        public boolean hasNext() { 
            //cursor 初始值为 0,没掉一次 next 方法就 +1 
            //size 是 ArrayList 的大小 
            return cursor != size; 
        } 
 
        @SuppressWarnings("unchecked") 
        public E next() {checkForComodification(); 
            int i = cursor; 
            if (i >= size) 
                throw new NoSuchElementException(); 
            // 把 ArrayList 中的数组赋给 elementData 
            Object[] elementData = ArrayList.this.elementData; 
            if (i >= elementData.length) 
                throw new ConcurrentModificationException(); 
            // 每调用一次 next 方法,游标就加 1 
            //cursor=lastRet+1 
            cursor = i + 1; 
            // 返回 ArrayList 中的元素 
            return (E) elementData[lastRet = i]; 
        } 
 
        public void remove() {if (lastRet 
再回到上面题目中:

第一个 iterator.hasNext()

第 1 次循环

hasNext 方法中:cursor==0,size==3,所以 cursor != size 返回 true。
next 方法中:cursor=0+1。返回 ”1″。

第 2 次循环

hasNext 方法中:cursor==1,size==3,所以 cursor != size 返回 true。
next 方法中:cursor=1+1。返回 ”2″。
remove 方法中:cursor==cursor-1==2-1=1,把 ArrayList 中的 ”2″ 给删除了,所以 size==2。

第 3 次循环

hasNext 方法中:cursor==1,size==2,那么 cursor != size 返回 true。
next 方法中:cursor=1+1==2; 返回 ”3″。

第 4 次循环

hasNext 方法中:cursor==2,size==2,那么 cursor != size 返回 false。
第二个 iterator.hasNext()

hasNext 方法中:cursor==2,size==2,所以 cursor != size 返回 false。

所以,最后只输出 ”4″,即答案为 4.

Iterator 与泛型搭配

Iterator 对集合类中的任何一个实现类,都可以返回这样一个 Iterator 对象。可以适用于任何一个类。
因为集合类 (List 和 Set 等) 可以装入的对象的类型是不确定的, 从集合中取出时都是 Object 类型, 用时都需要进行强制转化, 这样会很麻烦, 用上泛型, 就是提前告诉集合确定要装入集合的类型, 这样就可以直接使用而不用显示类型转换. 非常方便.

foreach 和 Iterator 的关系

for each 以用来处理集合中的每个元素而不用考虑集合定下标。就是为了让用 Iterator 简单。但是删除的时候,区别就是在 remove,循环中调用集合 remove 会导致原集合变化导致错误,而应该用迭代器的 remove 方法。

使用 for 循环还是迭代器 Iterator 对比

采用 ArrayList 对随机访问比较快,而 for 循环中的 get()方法,采用的即是随机访问的方法,因此在 ArrayList 里,for 循环较快
采用 LinkedList 则是顺序访问比较快,iterator 中的 next()方法,采用的即是顺序访问的方法,因此在 LinkedList 里,使用 iterator 较快
从数据结构角度分析,for 循环适合访问顺序结构, 可以根据下标快速获取指定元素. 而 Iterator 适合访问链式结构, 因为迭代器是通过 next()和 Pre()来定位的. 可以访问没有顺序的集合.
而使用 Iterator 的好处在于可以使用相同方式去遍历集合中元素,而不用考虑集合类的内部实现(只要它实现了 java.lang.Iterable 接口),如果使用 Iterator 来遍历集合中元素,一旦不再使用 List 转而使用 Set 来组织数据,那遍历元素的代码不用做任何修改,如果使用 for 来遍历,那所有遍历此集合的算法都得做相应调整, 因为 List 有序,Set 无序, 结构不同, 他们的访问算法也不一样.(还是说明了一点遍历和集合本身分离了)。

总结

迭代出来的元素都是原来集合元素的拷贝。
Java 集合中保存的元素实质是对象的引用,而非对象本身。
迭代出的对象也是引用的拷贝,结果还是引用。那么如果集合中保存的元素是可变类型的,那么可以通过迭代出的元素修改原集合中的对象。

阿里云 2 核 2G 服务器 3M 带宽 61 元 1 年,有高配

腾讯云新客低至 82 元 / 年,老客户 99 元 / 年

代金券:在阿里云专用满减优惠券

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-25发表,共计3791字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7798368
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

4盘位、4K输出、J3455、遥控,NAS硬件入门性价比之王

  4 盘位、4K 输出、J3455、遥控,NAS 硬件入门性价比之王 开篇 在 NAS 市场中,威...
【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024程序员】我劝你赶紧去免费领一个AWS、华为云等的主机

【1024 程序员】我劝你赶紧去免费领一个 AWS、华为云等的主机 每年 10 月 24 日,程序员们都会迎来...
星哥带你玩飞牛NAS-5:飞牛NAS中的Docker功能介绍

星哥带你玩飞牛NAS-5:飞牛NAS中的Docker功能介绍

星哥带你玩飞牛 NAS-5:飞牛 NAS 中的 Docker 功能介绍 大家好,我是星哥,今天给大家带来如何在...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛 NAS-4:飞牛 NAS 安装 istore 旁路由,家庭网络升级的最佳实践 开始 大家好我是...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛NAS-4:飞牛NAS安装istore旁路由,家庭网络升级的最佳实践

星哥带你玩飞牛 NAS-4:飞牛 NAS 安装 istore 旁路由,家庭网络升级的最佳实践 开始 大家好我是...
星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

  星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...
小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比 星哥玩云,带你从小白到上云高手。今天咱们就来聊聊——什...
如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的Nano Banana Pro?附赠邪修的用法

如何免费使用强大的 Nano Banana Pro?附赠邪修的用法 前言 大家好,我是星哥,今天来介绍谷歌的 ...