iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java面试必备之ArrayList陷阱解析
  • 158
分享到

Java面试必备之ArrayList陷阱解析

2024-04-02 19:04:59 158人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录问题分析疑惑满满拨云见日回顾整个过程如何正确的删除总结问题分析 疑惑满满 小枫听到这个面试题的时候,心想这是什么水面试官,怎么问这么简单的题目,心想一个for循环加上equal判

问题分析

疑惑满满

小枫听到这个面试题的时候,心想这是什么水面试官,怎么问这么简单的题目,心想一个for循环加上equal判断再删除不就完事了吗?但是转念一想,不对,这里面肯定有陷阱,不然不会问这么看似简单的问题。小枫突然想起来之前写代码的时候好像遇到过这个问题,也是在ArrayList中删除指定元素,但是直接for循环remove元素的时候还抛出了异常,面试官的陷阱估计在这里。小枫暗自窃喜,找到了面试官埋下的陷阱。 小枫回想起当天的的测试情况,代码进行了脱敏改造。当初是要在ArrayList中删除指定元素,小枫三下五除二,酣畅淋漓的写下了如下的代码,信心满满的点了Run代码的按钮,结果尴尬了,抛异常了。


public class TestListMain {

    public static void main(String[] args) {

        List<String> result = new ArrayList<>();
        result.add("a");
        result.add("b");
        result.add("c");
        result.add("d");

        for (String s : result) {
            if ("b".equals(s)) {
                result.remove("b");
            }
        }

    }
}

一个大大红色的异常马上就出来了,OMG,怎么会这样呢,感觉代码没什么问题啊,赶紧看看抛了什么异常,在哪里抛的异常吧。可以看出来抛了一个ConcurrentModificationException的异常,而且是在Itr这个类中的一个检测方法中抛出来的异常,这是怎么回事呢?我们的原始代码中并没有这个Itr代码,真是百思不得其解。

拨云见日

既然从源代码分析不出来,我们就看下源代码编译后的class文件中的内容是怎样的吧,毕竟class文件才是JVM真正执行的代码,不看不知道,一看吓一跳,jdk原来是这么玩的。原来如此,我们原始代码中的for-each语句,编译后的实际是以迭代器来代替执行的。


public class TestListMain {
    public TestListMain() {
    }

    public static void main(String[] args) {
        List<String> result = new ArrayList();
        result.add("a");
        result.add("b");
        result.add("c");
        result.add("d");
        //创建迭代器
        Iterator var2 = result.iterator();

        while(var2.hasNext()) {
            String s = (String)var2.next();
            if ("b".equals(s)) {
                result.remove("b");
            }
        }

    }
}

通过ArrayList创建的Itr这个内部类迭代器,于是for-each循环就转化成了迭代器加while循环的方式,原来看上去的for-each循环被挂羊头卖狗肉了。


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

Itr这个内部类迭代器,通过判断hasNext()来判断迭代器是否有内容,而next()方法则获取迭代器中的内容。


 private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int 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];
        }
     ...
     
 }

大致的过程如下所示:

真正抛异常的地方是这个检测方法, 当modCount与expectedModCount不相等的时候直接抛出异常了。那我们要看下modCount以及expectedModCount分别是什么。这里的modCount代表ArrayList的修改次数,而expectedModCount代表的是迭代器的修改次数,在创建Itr迭代器的时候,将modCount赋值给了expectedModCount,因此在本例中一开始modCount和expectedModCount都是4(添加了四次String元素)。但是在获取到b元素之后,ArrayList进行了remove操作,因此modCount就累加为5了。因此在进行检查的时候就出现了不一致,最终导致了异常的产生。到此我们找到了抛异常的原因,循环使用迭代器进行循环,但是操作元素却是使用的ArrayList操作,因此迭代器在循环的时候发现元素被修改了所以抛出异常。

我们再来思考下,为什么要有这个检测呢?这个异常到底起到什么作用呢?我们先来开下ConcurrentModificationException的注释是怎么描述的。简单理解就是不允许一个线程在修改集合,另一个线程在集合基础之上进行迭代。一旦检测到了这种情况就会通过fast-fail机制,抛出异常,防止后面的不可知状况。



public class ConcurrentModificationException extends RuntimeException {
    ...
}

回顾整个过程

如何正确的删除

既然抛异常的原因是循环使用了迭代器,而删除使用ArrayList导致检测不通过。那么我们就循环使用迭代器,删除也是用迭代器,这样就可以保证一致了。


public class TestListMain {

    public static void main(String[] args) {

        List<String> result = new ArrayList<>();
        result.add("a");
        result.add("b");
        result.add("c");
        result.add("d");

       Iterator<String> iterator = list.iterator();
 
		while (iterator .hasNext()) {
			String str = iterator.next();
			if ("b".equals(str)) {
				iterator.remove();
			}
    }
}

总结

本文主要对于ArrayList在for循环中进行元素删除出现的异常进行源码分析,这也是面试的时候经常出现的面试陷阱题,面试官通过这样看似简单的题目考察候选者的JDK源码的掌握程度。

真正的大师永远怀着一颗学徒的心

到此这篇关于Java面试必备之ArrayList陷阱解析的文章就介绍到这了,更多相关Java ArrayList内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java面试必备之ArrayList陷阱解析

本文链接: https://www.lsjlt.com/news/140271.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java面试必备之ArrayList陷阱解析
    目录问题分析疑惑满满拨云见日回顾整个过程如何正确的删除总结问题分析 疑惑满满 小枫听到这个面试题的时候,心想这是什么水面试官,怎么问这么简单的题目,心想一个for循环加上equal判...
    99+
    2024-04-02
  • Java中ArrayList陷阱实例分析
    这篇文章主要介绍“Java中ArrayList陷阱实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java中ArrayList陷阱实例分析”文章能帮助大家解决问题。问题分析疑惑满满小枫听到这个...
    99+
    2023-06-29
  • Python面试题陷阱实例分析
    这篇文章主要讲解了“Python面试题陷阱实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python面试题陷阱实例分析”吧!问题1:请问如何修改以下Python代码,使得下面的代码调...
    99+
    2023-06-17
  • 面试必备:Java 缓存知识全面解析!
    Java 缓存在面试中是一个非常重要的话题,因为它是提高应用程序性能的一个重要手段。本文将全面解析 Java 缓存的知识,为你在面试中更好地回答相关问题提供帮助。 一、什么是缓存? 缓存是一种提高程序性能的技术,它通过将常用的数据存储在快速...
    99+
    2023-10-06
    缓存 学习笔记 面试
  • Java面试必备之JMM高并发编程详解
    目录一、什么是JMM二、JMM定义了什么原子性可见性有序性三、八种内存交互操作四、volatile关键字可见性volatile一定能保证线程安全吗禁止指令重排序volatile禁止指...
    99+
    2024-04-02
  • Java面试必备八股文
    文章目录 一、Java基础篇1.1)Java有哪几种数据类型1.2)JVM、JRE和JDK的关系1.3)Switch支持的数据类型?1.4)为什么float=3.4报错1.5)final 有什么用?1.6)String有哪些特性1....
    99+
    2023-08-16
    java 面试 jvm
  • 面试必备之ajax原始请求
    目录XMLHttpRequest 对象简介XMLHttpRequest 的实例属性XMLHttpRequest.readyStateXMLHttpRequest.onreadysta...
    99+
    2024-04-02
  • 面试Java开发岗位必备技能之Load框架详解!
    Load框架是一种轻量级的Java Web框架,它是由国内知名的互联网公司开发的,具有简单易用、高效稳定、灵活扩展等特点,目前已经广泛应用于各大互联网公司的Java Web项目中。 下面,我们将详细介绍Load框架的核心特性和使用方法。 ...
    99+
    2023-11-09
    load 框架 面试
  • 存储关键字必备技能:Go语言面试必备问题解析
    Go语言是一门高效、简单、可靠的编程语言,越来越受到程序员的喜爱。如果你正在准备Go语言的面试,那么一定要掌握Go语言的存储关键字。下面是一些必备问题和解析,希望对你有所帮助。 什么是存储关键字? 存储关键字是指在Go语言中有特定含义...
    99+
    2023-08-19
    关键字 面试 存储
  • Java面试必备之AQS阻塞队列和条件队列
    一.AQS入队规则 我们仔细分析一下AQS是如何维护阻塞队列的,在独占方式获取资源的时候,是怎么将竞争锁失败的线程丢到阻塞队列中的呢? 我们看看acquire方法,这里首先会调用子类...
    99+
    2024-04-02
  • PHP面试必备:Load算法详解!
    在进行 PHP 面试时,Load 算法是一个非常重要的知识点。Load 算法是用来评估系统负载的一种算法,它可以帮助我们确定系统当前的运行状态,从而更好地进行系统优化。在本文中,我们将详细介绍 Load 算法的原理和实现,并提供实际的 P...
    99+
    2023-08-15
    面试 load 编程算法
  • 20道必备!PHP面试题及详细答案解析
    当今互联网时代,PHP已经成为一种广泛使用的服务器端脚本语言。如果您正在准备PHP的面试,那么您需要了解一些常见的PHP面试题。在本篇博客中,我们将提供20道常见的PHP面试题及其答案。 什么是PHP? 答:PHP是一种广泛使用的服务器端脚...
    99+
    2023-09-01
    php 开发语言 数据库
  • JavaScript面试必备技巧之手写一个Promise
    目录基本实现实现resolve和reject状态不可变then其他方法很多同学在面试的时候都会被要求手写一个Promise,那么今天我总结了一些手写Promise的方法,可以跟着我的...
    99+
    2023-02-08
    JavaScript实现手写Promise JavaScript手写Promise JavaScript Promise
  • Java面试必备:如何掌握Spring和Unix?
    在Java开发领域,Spring框架是一个非常常用的框架,它可以帮助我们更加方便、快捷地开发Java应用程序。而Unix则是一个非常流行的操作系统,它广泛应用于服务器端和开发环境中。在Java面试中,掌握Spring和Unix是非常重要的...
    99+
    2023-09-16
    面试 spring unix
  • Java架构师面试必备题(含答案)
    第一题:一条sql执行过长的时间,你如何优化,从哪些方面? 答:1、查看sql是否涉及多表的联表或者子查询,如果有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化) 2、涉及链表的查询,是否能进行分表查询,单表查询之...
    99+
    2023-09-15
    java 面试 数据库
  • Java面试岗常见问题之ArrayList和LinkedList的区别
    目录1.ArrayList和LinkedList是什么?2.ArrayList和LinkedList性能比较          &n...
    99+
    2024-04-02
  • 面试必备:ASP分布式开发常用函数解析
    在ASP分布式开发中,常用的函数可以让我们更高效地开发网站。以下是一些常用的函数,以及如何使用它们。 Server.MapPath Server.MapPath函数用于获取指定文件或文件夹在服务器上的物理路径。例如,如果您希望打开一个...
    99+
    2023-06-14
    分布式 面试 函数
  • Synchronized的底层实现原理(原理解析,面试必备)
    synchronized 一. synchronized解读 1.1 简单描述 synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized 翻译为中文的意思是同步,也称之为同步锁。 synchronize...
    99+
    2023-08-19
    面试 java jvm
  • Java开发者必读:Load框架面试题解析!
    在Java开发中,Load框架是一个非常重要的工具。如果你正在准备面试,那么你可能会遇到一些关于Load框架的问题。在本文中,我们将对一些常见的Load框架面试题进行解析,同时还会附上一些演示代码。 什么是Load框架? Load框架...
    99+
    2023-11-09
    load 框架 面试
  • PHP 面试必备:编程算法详解!
    在 PHP 开发领域,编程算法是非常重要的知识点。在面试过程中,面试官往往会考察面试者对编程算法的掌握程度。因此,掌握 PHP 编程算法是每个 PHP 开发者必须要做的功课之一。本文将详细介绍 PHP 编程算法的相关知识,并提供演示代码,...
    99+
    2023-06-04
    面试 编程算法 分布式
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作