首页 > 编程语言 >Java List常见面试题

Java List常见面试题

时间:2023-09-02 11:31:57浏览次数:72  
标签:面试题 Java LinkedList ArrayList List CopyOnWriteArrayList Vector 线程 数组

Java集合面试之List篇

你好,面试官 | 我用Java List 狂怼面试官~ (qq.com)

本文涉及ArrayList 与 LinkedList 区别、ArrayList 扩容机制、CopyOnWriteArrayList 特点、场景、思想

  • ArrayList : 基于数组实现的非线程安全的集合。实现 RandomAccess 接口,支持随机访问,查询元素快,插入,删除中间元素慢。
  • LinkedList : 基于链表实现的非线程安全的集合。查询元素慢,插入,删除中间元素快,一般情况占用空间大(维护双指针)。
  • Vector : 基于数组实现的线程安全的集合。线程同步(方法被synchronized修饰),性能比 ArrayList 差。
  • CopyOnWriteArrayList : 基于数组实现的线程安全的写时复制集合。线程安全(ReentrantLock加锁),性能比Vector高,适合读多写少的场景,最终一致性。

ArrayList 和 LinkedList 的区别是什么?

(1)数据结构:ArrayList是动态数组,而 LinkedList 是双向链表。

(2)随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。

(3)增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响其他数据下标。

(4)内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。

(5)线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;

讲讲ArrayList的扩容机制

ArrayList 添加元素时使用 ensureCapacityInternal()方法来保证容量足够,如果不够时,需要使用 grow() 方法进行扩容

新容量的大小为 oldCapacity + (oldCapacity >> 1),即 oldCapacity+oldCapacity/2。其中 oldCapacity >> 1 需要取整,所以新容量大约是旧容量的 1.5 倍左右。

扩容操作需要调用Arrays.copyOf() 把原数组整个复制到新数组中,这个操作代价很高,因此最好在创建 ArrayList 对象时就指定大概的容量大小,减少扩容操作的次数,最好会利用 modCount 记录结构修改次数。

ArrayList 和 LinkedList 都是非线程安全的,需要考虑并发问题时怎么办?

第一个办法,使用Vector,Vector 和 ArrayList 差不多,不过它对数据操作的方法都加了synchronized,因此它是线程安全的,不过由于加了 synchronized,线程同步,导致 Vector 性能很差。

第二个办法,使用Collections.synchronizedList(list)方法或者使用 CopyOnWriteArrayList 集合。

ArrayList 和 Vector 的区别是什么?

(1)线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。

(2)性能:ArrayList 在性能方面要优于 Vector。

(3)扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。

介绍一下CopyOnWriteArrayList

CopyOnWriteArrayList,它是一个写时复制的容器。何为写时复制呢?

当我们往一个容器添加元素的时候,不是直接往当前容器添加,而是先将当前容器进行 copy一份,复制出一个新的容器,然后对新容器里面操作元素,最后将原容器的引用指向新的容器。

它实现了List接口,内部持有 ReentrantLock 对象,底层使用 volatile transient 声明得数组,能更好的处理锁竞争问题,在并发高时,比 Vector 性能更佳,读写分离,写时复制,先用 ReetrantLock 对象加锁,然后会复制一份原数组进行写操作,写完了再将新数组值赋予原数组。适合读多写少场景

CopyOnWriteArrayList的缺点你说说

正因为它写时复制的特性,因此每次写都要复制一个数组,很耗费内存的,数据量大时,对内存压力较大,可能会引起频繁 GC。

还有就是大量写操作性能极差,所以只适合读多写少的

并且无法保证实时性Vector对于读写操作均加锁同步,可以保证读和写的强一致性。而 CopyOnWriteArrayList 由于其实现策略的原因,写和读分别作用在新老不同容器上,在写操作执行过程中,读不会阻塞但读取到的却是老容器的数据。

CopyOnWriteArrayList为什么无法保证实时性

因为 COW(CopyOnWrite)写时复制,CopyOnWriteArrayList 读取时不加锁,只是写入、删除、修改时加锁,由于所有的写操作都是在新数组进行的,这个时候如果有线程并发的写,则通过锁来控制,如果有线程并发的读,则分几种情况

  1. 如果写操作未完成,那么直接读取原数组的数据;
  2. 如果写操作完成,但是引用还未指向新数组,那么也是读取原数组数据;
  3. 如果写操作完成,并且引用已经指向了新的数组,那么直接从新数组中读取数据。

因此,对 CopyOnWriteArrayList 进行增删改操作,与此同时有其他线程来访问 CopyOnWriteArrayList 中的元素,因为增删改操作未完成,所以读取元素的线程看不到新数据。可能会读到脏数据。

标签:面试题,Java,LinkedList,ArrayList,List,CopyOnWriteArrayList,Vector,线程,数组
From: https://blog.51cto.com/u_15872442/7331611

相关文章

  • Java入门
    Java初识Java发展史时间节点1991年,Sun公司进军嵌入式开发,让电视、冰箱、微波炉等设备能够用上编程语言,成立了Green项目小组;1992年,由于C++语言的繁琐且不支持跨平台,研发团队基于C++开发了Oak语言;1995年,互联网大爆发,跨平台的特性使得Oak语言得到飞速发展,同时正式更名为Java(爪......
  • 20230829-面试题html+css5道题记录
    css预处理工具参考答案:CSS预处理器是一个能让你通过预处理器自己独有的语法来生成CSS的程序。css预处理器种类繁多,三种主流css预处理器是Less、Sass(Scss)及Stylus;它们各自的背景如下:Sass:2007年诞生,最早也是最成熟的CSS预处理器,拥有ruby社区的支持和compass这一最强大的css框......
  • 20230825-面试题html+css5篇简单记录
    html标签的类型(head,body,!Doctype)他们的作用是什么!DOCTYPE标签:它是指示web浏览器关于页面使用哪个HTML版本进行编写的指令.head:是所有头部元素的容器,绝大多数头部标签的内容不会显示给读者该标签下所包含的部分可加入的标签有base,link,meta,script,style和title......
  • 用友致远U8-OA getSessionList jsp信息泄露复现
    1.漏洞描述用友U8-OAgetSessionList.jsp存在漏洞,攻击者通过该漏洞可以获取到所有用户的sessionID,利用获取到的sessionID即可登录到系统。2.网络测绘fofa:"用友U8-OA"3.漏洞复现1.登录页面2.验证POC/yyoa/ext/https/getSessionList.jsp?cmd=getAll3.将其拼......
  • android面试题:谈谈对Java中多态的理解
     Java中的多态是面向对象编程的一个重要特征,它允许同一个类型的对象在不同的情况下表现出不同的行为。多态是Java语言中实现代码复用、提高代码可维护性和可扩展性的重要手段。 多态的实现基于两个核心概念:继承和方法重写。在Java中,子类可以继承父类的方法,并且可以重写(覆......
  • 剑指 Offer 48. 最长不含重复字符的子字符串 java
    请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。示例1:输入:"abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:"bbbbb"输出:1解释:因为无重复字符的最长子串是"b",所以其长度为1。示例3:输入......
  • java基础-流程控制-day04
    目录1.if单分支2.ifelse多分支3.ifelse双分支4.随机生成一定区间的整数5switch1.if单分支publicclassTestIf01{ publicstaticvoidmain(String[]args){ //对三个数(1-6)求和 intnum1=6; intnum2=6; intnum3=5; intsum=0; sum+=nu......
  • .Net6.0 Redis操作其一List篇
    今天在写字典表时为了优化就用了redis,然后其中就又用到了redis中的一个LIst添加和读取的操作首先Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sortedset:有序集合)。今天讲的是其中之一lIst(列表)Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加......
  • 【2023年下半年Java开发行情预测】
    2023年下半年Java开发行情预测,需要考虑多种因素,包括市场需求、技术发展趋势、人才供需关系等。以下是我对Java开发行情的一些预测:市场需求将继续保持增长:随着数字化转型的加速,许多企业需要将业务迁移到云端,这将导致对Java开发人员的需求增加。此外,Java作为一门流行的编程语言,其需......
  • java拷贝对象列表List copyProperties
    <!--hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.0.6</version></dependency>/***@Author:Fcx*@Date:2019/11/2020:45*@Versio......