面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?

本文主要是介绍面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在开头

某大厂的面试现场,一位目光深邃,头顶稀疏的中年面试官坐在椅子上,这时候的我走了进来。
面试官:“小伙子,学过Java中容器和数据结构了吧?”
我:“嗯,学了”
面试官:“ok,那你来聊一聊Java中的迭代器(Iterator ),要说清楚他们的应用场景哈”
我:“哦,好滴”
内心独白:“这面试官不按套路出牌啊,本来以为会问问ArrayList,HashMap呢,或者手撕排序算法,这上来直接让撕迭代器”
虽然面试官不按套路出牌,但这时我们也不能乱,迅速的平复心情后,大脑飞速运转,回想着之前学的内容,其实迭代器和比较器确实在容器和数据结构中有所体现。

Iterator (迭代器)

在解释迭代器之前,我们先来聊一下23种设计模式之一:迭代器模式,它是 Java 中常用的设计模式之一。用于顺序访问集合对象的元素,无需知道集合对象的底层实现。
而Iterator则是在这种设计思想下诞生的产物,Iterator 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。

【源码解析1】

public interface Iterator<E> {//是否有下一个元素boolean hasNext();//下一个元素E next();//从迭代器指向的集合中删除迭代器返回的最后一个元素default void remove() {throw new UnsupportedOperationException("remove");}//遍历所有元素default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}
}

那我们日常使用中如何通过迭代器去遍历集合中的数据呢?我们接下往下看(一步一步耐心的给面试官解释,不要紧张,保持逻辑清楚!)

【代码示例1】

public class Test {public static void main(String[] args) {ArrayList<String> str = new ArrayList<>();str.add("aaa");str.add("bbb");str.add("ccc");//迭代器遍历Iterator it = str.iterator();while (it.hasNext()) {System.out.print(it.next() + ",");}}
}

输出:

aaa,bbb,ccc,

我们创建一个包含ArrayList容器,里面包含aaa,bbb,ccc元素,通过调用str对象的iterator()方法去遍历元素,然后将遍历的元素打印出来,如上输出(这部分可以手撕给面试官看,方便后续的展开阐述)

面试官:“那你知道为什么ArrayList可以调用迭代器方法吗,底层逻辑有没有看过?”

当面试官问到这个问题的时候,我们心中一喜,因为他成功的被我们引导到了我们熟悉的方向上,那么接下来,我们要好好唠一唠了!

我:“嗯,之前学习的时候,有跟过这部分底层源码,我说说看,不对的麻烦您多给指正哈”

我们知道Collection是Set、List、Queue的父接口,而Collection接口又继承了另外一个接口,叫Iterable,得到了它的一个接口方法iterator()。

【源码解析2】

public interface Collection<E> extends Iterable<E> {...Iterator<E> iterator();...

而对于我们日常使用的集合类来说,如ArrayList,它的继承关系让它可以得到iterator对象,我们可以画一个流程图来分析一下。
在这里插入图片描述
ArrayList中重写了AbstractList中的iterator()方法,并返回一个内部类对象Itr,我们看一下这个内部类的实现源码。

【源码解析3】

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];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}// update once at end of iteration to reduce heap write trafficcursor = i;lastRet = i - 1;checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}

讲到这里,我们可以给一个阶段性的总结:所以在继承了Collection接口,并实现了iterator()方法的所有集合类,都可以使用迭代器进行元素的遍历。
【温馨提示】
若此时的你足够强大,足够自信,还可以进一步引出增强for循环遍历,它的底层原理也是Iterator

【代码示例2】

for (String str : list) {System.out.print(str + ",");
}

【反编译】

Iterator var3 = list.iterator();while(var3.hasNext()) {String str = (String)var3.next();System.out.print(str + ",");
}

反编译后我们可以看得出,底层的实现就是迭代器,而这个for-each的写法不过是Java的一个语法糖罢了,这部分属于附加题,讲不明白的,可以不提。
本来以为迭代器这个话题到此就结束了,没想到面试官紧接着又抛出了一个问题
面试官:“LinkedList也是如此吗?”
听到这里咱们心里一紧,他终究是要挖光我们的家底呀
确实!LinkedList有所不同,LinkedList 并没有直接重写 Iterable 接口的 iterator 方法,而是由它的父类 AbstractSequentialList 来完成。
进入源码会发现,这个AbstractSequentialList 中提供了一个listIterator对象,而LinkedList进行了方法的重写。
【源码解析4】

public interface ListIterator<E> extends Iterator<E> {boolean hasNext();E next();boolean hasPrevious();E previous();
}

这让它拥有了可以从任意下标开始遍历,而且支持双向遍历的能力。注意ListIterator只支持List类型集合。
到此,我们对于Iterator的了解全盘拖出了,当然还有一些细枝末节的知识,但我相信能回答到这里,已经获得面试官的认可啦。

结尾彩蛋

如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

在这里插入图片描述

这篇关于面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/734278

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Springboot项目启动失败提示找不到dao类的解决

《Springboot项目启动失败提示找不到dao类的解决》SpringBoot启动失败,因ProductServiceImpl未正确注入ProductDao,原因:Dao未注册为Bean,解决:在启... 目录错误描述原因解决方法总结***************************APPLICA编

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Apache Ignite 与 Spring Boot 集成详细指南

《ApacheIgnite与SpringBoot集成详细指南》ApacheIgnite官方指南详解如何通过SpringBootStarter扩展实现自动配置,支持厚/轻客户端模式,简化Ign... 目录 一、背景:为什么需要这个集成? 二、两种集成方式(对应两种客户端模型) 三、方式一:自动配置 Thick

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

Java.lang.InterruptedException被中止异常的原因及解决方案

《Java.lang.InterruptedException被中止异常的原因及解决方案》Java.lang.InterruptedException是线程被中断时抛出的异常,用于协作停止执行,常见于... 目录报错问题报错原因解决方法Java.lang.InterruptedException 是 Jav