【Java集合】面试题汇总

news2024/10/7 12:25:06

  • Java 集合
    • Java 集合概览
    • 1. List, Set, Queue, Map 四者的区别?
    • 2. ArrayList 和 Array(数组)的区别?
    • 3. ArrayList 和 Vector 的区别?
    • 4. Vector 和 Stack 的区别?(了解即可)
    • 5. ArrayList 可以添加 null 值吗?
    • 6. ArrayList 插入和删除元素的时间复杂度?
    • 7. LinkedList 插入和删除元素的时间复杂度?
    • 8. LinkedList 为什么不能实现 RandomAccess 接口?
    • 9. ArrayList 与 LinkedList 区别?
    • 10. 说一说 ArrayList 的扩容机制
    • 11. Comparable 和 Comparator 的区别
    • 12. 比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同
    • 13. Queue 与 Deque 的区别
    • 14. ArrayDeque 与 LinkedList 的区别
    • 15. 说一说 PriorityQueue
    • 16. 什么是 BlockingQueue?
    • 17. BlockingQueue 的实现类有哪些?
    • 18. ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
    • 19. HashMap 和 Hashtable 的区别
    • 20. HashMap 和 HashSet 区别
    • 21. HashMap 和 TreeMap 区别
    • 22. HashSet 如何检查重复?
    • 23. HashMap 的底层实现
    • 24. HashMap 的长度为什么是 2 的幂次方
    • 25. HashMap 多线程操作导致死循环问题
    • 26. HashMap 为什么线程不安全?
    • 27. HashMap 常见的遍历方式?
    • 28. ConcurrentHashMap 和 Hashtable 的区别
    • 29. JDK 1.7 和 JDK 1.8 的 ConcurrentHashMap 实现有什么不同?
    • 30. ConcurrentHashMap 为什么 key 和 value 不能为 null?
    • 31. ConcurrentHashMap 能保证复合操作的原子性吗?
    • 32. ArrayList 扩容机制分析
    • 33. HashMap 扩容机制分析
    • 34. CopyOnWriteArrayList 简介

Java 集合

Java 集合概览

答:

Java 集合,也叫作容器,主要是由两大接口派生而来

  • Collection 接口
  • Map 接口

Java 集合框架如下图所示:

在这里插入图片描述

1. List, Set, Queue, Map 四者的区别?

答:

  • List:存储的元素是有序的、可重复的。
  • Set:存储的元素是无序的、不可重复的。
  • Queue:存储的元素可重复,元素先进先出。
  • Map:使用键值对(key-value)存储元素。key 是无序的、不可重复的

2. ArrayList 和 Array(数组)的区别?

答:

  • ArrayList 支持动态的扩容,Array被创建后不能改变长度了。
  • ArrayList 只能存储对象类型,Array可以存储对象类型和基本数据类型。

3. ArrayList 和 Vector 的区别?

答:

  • ArrayList线程不安全
  • Vector线程安全 。

4. Vector 和 Stack 的区别?(了解即可)

答:

  • Vector 和 Stack 两者都是线程安全的,都是使用 synchronized 关键字进行同步处理。
  • Stack 继承自 Vector,是一个先进后出的栈,而 Vector 是一个列表。

注意: Vector 和 Stack 已经被淘汰,推荐使用并发集合类(例如 ConcurrentHashMapCopyOnWriteArrayList

5. ArrayList 可以添加 null 值吗?

答:

  • 可以

6. ArrayList 插入和删除元素的时间复杂度?

答:

插入:

  • 头部插入:O(n)
  • 尾部插入:如果容量未到极限O(1),到达极限O(n)
  • 指定位置插入:O(n)

删除:

  • 头部删除:O(n)
  • 尾部删除:O(1)
  • 指定位置删除:O(n)

7. LinkedList 插入和删除元素的时间复杂度?

答:

插入:

  • 头部插入:O(1)
  • 尾部插入:O(1)
  • 指定位置插入:O(n)

删除:

  • 头部删除:O(1)
  • 尾部删除:O(1)
  • 指定位置删除:O(n)

8. LinkedList 为什么不能实现 RandomAccess 接口?

答:

  • RandomAccess 是一个标记接口,用来表明实现该接口的类支持随机访问(即可以通过索引快速访问元素)。
  • 由于 LinkedList 底层数据结构是链表,内存地址不连续,只能通过指针来定位,不支持随机快速访问,所以不能实现 RandomAccess 接口

9. ArrayList 与 LinkedList 区别?

答:

  • ArrayList 底层使用的是 Object 数组,因为内存地址连续,可以实现随机访问。ArrayList会预留一定的空间容量。
  • LinkedList 底层使用的是 双向链表(JDK1.6 之前为循环链表),不支持随机访问。LinkedList存储的每个元素要比ArrayList的多(因为要存放后继和前驱节点)。

10. 说一说 ArrayList 的扩容机制

答:

  • 如果调用 ArrayList 的无参构造器的话,默认创建10个大小的容量。
  • 如果添加的元素超过了10,则会创建一个原先容量1.5倍大小的数组。
  • 再将原数组的数据拷贝过去。

11. Comparable 和 Comparator 的区别

答:

  • Comparable 接口和 Comparator 接口都是 Java 中用于排序的接口。
  • Comparable:
    • 要排序的对象实现Comparable 接口,重写 compareTo 方法
  • Comparator:
    • 通常需要使用匿名内部类来实现 Comparator 接口,并重写其中的 compare 方法
Collections.sort(arrayList, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2.compareTo(o1);
    }
});

12. 比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同

答:

相同点:

  • 他们都是 set 接口的实现类,都能保证元素的唯一性,都不是线程安全的。

不同点:

底层实现的数据结构不一样。

  • HashSet 底层使用的是 HashMap 实现的。
  • LinkedHashSet 的底层数据结构是链表和哈希表
  • TreeSet 底层是红黑树实现的。

底层实现的数据结构不一样,又会影响他们的使用场景不一样。

  • LinkedHashSet 能够保证插入的元素顺序。
  • TreeSet 支持自定义排序规则

13. Queue 与 Deque 的区别

答:

  • Queue单端队列,只能从一端插入元素,另一端删除元素。
  • Deque双端队列,在队列的两端均可以插入或删除元素。可以模拟栈

14. ArrayDeque 与 LinkedList 的区别

答:

ArrayDequeLinkedList 都实现了 Deque 接口,两者都具有队列的功能

区别:

  • ArrayDeque 是基于可变长的数组和双指针来实现,而 LinkedList 则通过链表来实现。
  • ArrayDeque 不支持存储 NULL 数据,但 LinkedList 支持。
  • ArrayDeque 插入时可能存在扩容LinkedList 插入时需要申请堆空间

15. 说一说 PriorityQueue

答:

PriorityQueue 优先级队列,实现了 Queue 接口。总是优先级最高的元素先出队。

特点:

  • PriorityQueue 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据。
  • PriorityQueue 插入元素和删除堆顶元素的时间复杂度为 O(logn)
  • PriorityQueue非线程安全的,且不支持存储 NULLnon-comparable 的对象。
  • PriorityQueue 默认是小顶堆,但可以接收一个 Comparator 作为构造参数,从而来自定义元素优先级。

16. 什么是 BlockingQueue?

答:

BlockingQueue (阻塞队列)是一个接口,继承自 Queue

  • 当要取队列中的元素时,如果队列为空,则会阻塞等待,直到有元素为止。
  • 当要将元素放入队列时,如果队列满了,则会阻塞等待,直到有其他元素出队列。

BlockingQueue 常用于生产者-消费者模型中,生产者线程会向队列中添加数据,而消费者线程会从队列中取出数据进行处理。

在这里插入图片描述

17. BlockingQueue 的实现类有哪些?

答:

在这里插入图片描述

Java 中常用的阻塞队列实现类有以下几种:

  • ArrayBlockingQueue:使用数组实现的有界阻塞队列。在创建时需要指定容量大小,并支持公平和非公平两种方式的锁访问机制。
  • LinkedBlockingQueue:使用单向链表实现的可选有界阻塞队列。在创建时可以指定容量大小,如果不指定则默认为Integer.MAX_VALUE。和ArrayBlockingQueue不同的是, 它仅支持非公平的锁访问机制。
  • PriorityBlockingQueue:支持优先级排序的无界阻塞队列。元素必须实现Comparable接口或者在构造函数中传入Comparator对象,并且不能插入 null 元素。
  • SynchronousQueue:同步队列,是一种不存储元素的阻塞队列。每个插入操作都必须等待对应的删除操作,反之删除操作也必须等待插入操作。因此,SynchronousQueue通常用于线程之间的直接传递数据。
  • DelayQueue:延迟队列,其中的元素只有到了其指定的延迟时间,才能够从队列中出队。

18. ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?

答:

  • 底层实现:ArrayBlockingQueue 基于数组实现,而 LinkedBlockingQueue 基于链表实现
  • 是否有界:ArrayBlockingQueue 是有界队列,必须在创建时指定容量大小。LinkedBlockingQueue 创建时可以不指定容量大小,默认是Integer.MAX_VALUE,也就是无界的。但也可以指定队列大小,从而成为有界的。
  • 锁是否分离: ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁;LinkedBlockingQueue中的锁是分离的,即生产用的是putLock,消费是takeLock,这样可以防止生产者和消费者线程之间的锁争夺。

19. HashMap 和 Hashtable 的区别

答:

  • HashMap 不是线程安全,Hashtable 线程安全
  • HashMap 的 key 和 value 可以存储 null 值Hashtable 的 key 和 value 不可以存储 null 值
  • JDK8 之后,HashMap的底层数据结构发生了变化(当链表长度大于阈值(默认为 8)时,将链表转化为红黑树(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)),Hashtable的底层数据结构是数组 + 链表。

20. HashMap 和 HashSet 区别

答:

  • HashSet 的底层实现就是 HashMap
  • HashSet 实例化时,内部其实就是创建了一个 HashMap
  • 调用 HashSet 的 add()方法,就是执行 HashMapput () 方法。

21. HashMap 和 TreeMap 区别

答:

  • TreeMap 实现了 NavigableMap 接口和 SortedMap 接口。
  • 相比于 HashMap ,多了对集合中的元素根据键排序的能力以及对集合内元素的搜索的能力。
  • NavigableMap 接口提供了丰富的方法来搜索和操作键值对,这些方法是基于红黑树的属性实现的,保证了搜索操作的时间复杂度为 O(log n)

22. HashSet 如何检查重复?

答:

  • 当一个元素加入 HashSet 时,首先会根据 hashcode 生成对应的哈希码,确定元素在哈希表中的位置。
  • 当对应位置没有元素时,则会加入到该位置。
  • 如果该位置已经有元素了,则会调用 equals() 方法比较对象的属性是否相同。如果相同则认为是重复元素,则加入失败。
  • 如果对象属性不相同,则会加入到对应位置的链表或是红黑树中。

23. HashMap 的底层实现

答:

哈希流程:

  • HashMap 首先获得 key 的 hashcode ,之后再经过扰动函数(hash函数)处理过后得到 hash 值(再经过hash函数是为了减少碰撞冲突
  • 然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度)
  • 如果当前位置存在元素的话,就通过 eaquls() 判断key是否相同。相同的话,直接覆盖,不相同通过拉链法解决冲突。

JDK 8之前

  • HashMap 底层是数组和链表

JDK 8之后

  • 当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
  • 为什么使用红黑树?: 红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构

24. HashMap 的长度为什么是 2 的幂次方

答:

  • 提高运算速度。当长度为 2 的幂次方时, hash%lengthhash&(length-1) 等价,但是位操作效率更高。
  • 减少冲突

25. HashMap 多线程操作导致死循环问题

答:

  • JDK 8之前,HashMap的链表是采取头插法,再多线程情况下可能导致形成环形链表,使查询陷入死循环。
  • JDK 8之后,采用尾插法,避免形成环形链表。
  • 但是在并发环境下,推荐使用 ConcurrentHashMap

26. HashMap 为什么线程不安全?

答:

  • 比如有2个线程同时进行 put 操作。
  • 线程1要插入的元素经过哈希后,确定了要插入的位置。并且此时时间片执行完毕。
  • 线程2获得CPU,线程2同时也要插入对应的位置,线程2插入对应的位置。
  • 线程1获得CPU后,会直接插入到该位置,那么就会覆盖线程2的数据。

27. HashMap 常见的遍历方式?

答:

  • 迭代器(Iterator)方式遍历
  • For Each 方式遍历
  • Streams API 遍历

28. ConcurrentHashMap 和 Hashtable 的区别

答:

实现线程安全的方式不同:

  • Hashtable 使用的是全局锁,任何时刻只能有一个线程进行操作。在并发环境下,效率是非常低。
  • JDK 8之前的 ConcurrentHashMap
    • 分段的数组 + 链表实现的,锁的是每一个段,每个段就相当于是一个Hashtable。
    • 在并发场景下,多线程访问不同的段,就不会存在锁竞争。
  • JDK 8之后的 ConcurrentHashMap
    • Node 数组 + 链表 / 红黑树 实现的,采用 CAS + synchronized 来保证并发安全。
    • synchronized 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发

29. JDK 1.7 和 JDK 1.8 的 ConcurrentHashMap 实现有什么不同?

答:

  • 线程安全实现方式:JDK 1.7 采用 Segment 分段锁来保证安全, Segment 是继承自 ReentrantLock。JDK1.8 采用 Node + CAS + synchronized 保证线程安全,锁粒度更细,synchronized 只锁定当前链表或红黑二叉树的首节点
  • Hash 碰撞解决方法:JDK 1.7 采用拉链法,JDK1.8 采用拉链法结合红黑树。
  • 并发度:JDK 1.7 最大并发度是 Segment 的个数,默认是 16。JDK 1.8 最大并发度是 Node 数组的大小,并发度更大。

30. ConcurrentHashMap 为什么 key 和 value 不能为 null?

答:

  • 避免二义性,如果 key 和 value 可以为null,那么在并发场景下,不知道这个值本身就是 null,还是其他线程修改的null。

31. ConcurrentHashMap 能保证复合操作的原子性吗?

答:

  • 可以使用 ConcurrentHashMap 提供的原子性复合操作。
  • putIfAbsentcomputecomputeIfAbsentcomputeIfPresentmerge

32. ArrayList 扩容机制分析

答:

  • 当添加元素到 ArrayList 时,它会检查当前元素数量是否已经超过了当前容量(内部通过 capacity 属性记录容量),如果超过了,则会进行扩容操作。
  • 当 ArrayList 需要扩容时,它会创建一个新的更大的数组,通常是原来容量的 1.5 倍。然后将旧的元素复制到新的数组中。

33. HashMap 扩容机制分析

答:

  • HashMap 默认的初始化大小为 16。之后每次扩充,容量变为原来的 2 倍
  • HashMap 总是使用 2 的幂作为哈希表的大小。

34. CopyOnWriteArrayList 简介

答:

  • CopyOnWriteArrayList 是并发安全的 List
  • 采用了 写时复制(Copy-On-Write) 的策略
  • 即在进行修改操作(add,set、remove)的时候,先创建底层数组的副本,对副本数组进行修改
  • 修改完之后再将修改后的数组赋值回去,这样就可以保证写操作不会影响读操作了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python+appium调@pytest.mark.parametrize返回missing 1 required positional argument:

出错描述&#xff1a; 1、在做pythonappium自动化测试时&#xff0c;使用装饰器pytest.mark.parametrize&#xff08;“参数”&#xff0c;[值1&#xff0c;值2&#xff0c;值3]&#xff09;&#xff0c;测试脚本执行返回test_xx() missing 1 required positional argument:“…

Bitmap OOM

老机器Bitmap预读仍然OOM&#xff0c;无奈增加一段&#xff0c;终于不崩溃了。 if (Build.VERSION.SDK_INT < 21)size 2; 完整代码&#xff1a; Bitmap bitmap; try {//Log.e(Thread.currentThread().getStackTrace()[2] "", surl);URL url new URL(surl);…

通俗易懂HTTP和HTTPS区别

HTTP&#xff1a;超文本传输协议&#xff0c;它是使用一种明文的方式发送我们的内容&#xff0c;没有任何的加密&#xff0c;例如我们要在网页上输入账号密码&#xff0c;如果使用HTTP协议&#xff0c;账号密码就可能会被暴露&#xff0c;默认端口是80. HTTPS&#xff1a;是HT…

动态规划解决背包问题

目录 动态规划步骤&#xff1a; 1.01背包问题 2.完全背包问题 动态规划步骤&#xff1a; step1.分析问题&#xff0c;定义dp数组&#xff08;下标含义&#xff09; step2.初始化dp数组&#xff08;边界&#xff09; step3.写dp状态转换方程&#xff08;明确dp数组遍历顺序…

【Super数据结构】二叉搜索树与二叉树的非递归遍历(含前/中/后序)

&#x1f3e0;关于此专栏&#xff1a;Super数据结构专栏将使用C/C语言介绍顺序表、链表、栈、队列等数据结构&#xff0c;每篇博文会使用尽可能多的代码片段图片的方式。 &#x1f6aa;归属专栏&#xff1a;Super数据结构 &#x1f3af;每日努力一点点&#xff0c;技术累计看得…

【饿了么笔试题汇总】[全网首发]2024-04-12-饿了么春招笔试题-三语言题解(CPP/Python/Java)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新饿了么近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x…

.cur 鼠标光标文件读取

备份icon掩码开发代码-CSDN博客 代码改写自 目前bug是高度不足&#xff0c;顶上的几十个像素图片打印需要加常数&#xff0c; i的改写是 i/3,参考上面链接的自简书的代码 #include <stdio.h> #include <windows.h> #pragma warning(disable : 4996) // visu…

[lesson20]初始化列表的使用

初始化列表的使用 类成员的初始化 C中提供了初始化列表对成员变量进行初始化 语法规则 注意事项 成员的初始化顺序与成员的声明顺序相同成员的初始化顺序与初始化列表中的位置无关初始化列表先于构造函数的函数体执行 类中的const成员 类中的const成员会被分配空间的类中…

【Linux】环境搭建

昙花一现&#xff0c;却等待了整个白昼 蝉鸣一夏&#xff0c;却蛰伏了几个四季 目录 购买云服务器 总结 使用 XShell 远程登陆到 Linux 利用Linux编写一个简单C程序 ⭐toush -- 创建文件 ⭐vi -- 文本编译器 ⭐ll -- 查看文件的显示结果分析 ⭐gcc -o ⭐cat -- 查看源代码 契子…

利用细粒度检索增强和自我检查提升对话式问题解答能力

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 论文标题&#xff1a;Boosting Conversational Question Answering with Fine-Grained Retrieval-Augmentation and Self-Check 论文地址&#xff1a;https://arxiv.org/abs/2403.18243 检索增强生成…

【报错】AttributeError: ‘NoneType‘ object has no attribute ‘pyplot_show‘(已解决)

【报错】AttributeError: ‘NoneType’ object has no attribute ‘pyplot_show’ 问题描述&#xff1a;python可视化出现下面报错 我的原始代码&#xff1a; import matplotlib.pyplot as pltplt.figure() plt.plot(x, y, bo-) plt.axis(equal) plt.xlabel(X) plt.ylabe…

最短路径问题——(弗洛伊德算法与迪杰斯特拉算法)

最短路径问题——&#xff08;弗洛伊德算法与迪杰斯特拉算法&#xff09;【板子】 题目&#xff1a; 对于下面的图片所给出的关系,回答下面两个问题&#xff1a; 利用迪杰斯特拉算法求点A到每一个点之间的最小距离。利用弗洛伊德算法求每两个点之间的最短路径。 &#xff0…

[RK3399 Linux] 使用ubuntu 20.04.5制作rootfs

一、ubuntu base ubuntu base是用于为特定需求创建自定义映像的最小rootfs,是ubuntu可以运行的最小环境。 1.1 下载源码 下载ubuntu-base的方式有很多,可以从官方的地址:ttp://cdimage.ubuntu.com/ubuntu-base/releases。 也可以其它镜像地址下载,如清华源:https://mi…

弹性云服务器性能对比(内附测试数据),快快网络服务器崭露头角

随着计算技术的不断革新&#xff0c;云服务器已成为企业和个人部署应用与服务的首选。尤其线上业务日益盛行的今天&#xff0c;云服务商的实力更是备受瞩目。对于企业而言&#xff0c;高稳定&#xff0c;存储速度都是不可或缺的基本要求&#xff0c;这些都对公有云的云端编解码…

算法 囚犯幸存者

题目 主类 public static List<Prisoner> prisoners new ArrayList<Prisoner>(); public static List<Prisoner> remainPrisoners new ArrayList<Prisoner>(); public static Prisoner lastPrisoner null;public static void main(String[] args) …

Fastgpt配合chatglm+m3e或ollama+m3e搭建个人知识库

概述&#xff1a; 人工智能大语言模型是近年来人工智能领域的一项重要技术&#xff0c;它的出现标志着自然语言处理领域的重大突破。这些模型利用深度学习和大规模数据训练&#xff0c;能够理解和生成人类语言&#xff0c;为各种应用场景提供了强大的文本处理能力。AI大语言模…

VulnHub靶机-easy_cloudantivirus 打靶

easy_cloudantivirus 靶机 目录 easy_cloudantivirus 靶机一、导入虚拟机配置二、攻击方式主机发现端口扫描web渗透-SQL注入命令注入反弹shellssh爆破提权 一、导入虚拟机配置 靶机地址&#xff1a; https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/下载完成&am…

golang实现定时监控 CLOSE_WAIT 连接的数量

文章目录 go实现定时检查大量的 CLOSE_WAIT 连接背景&#xff1a;为什么监控指定端口上的 CLOSE_WAIT 连接数量原因&#xff1a;什么是CLOSE_WAITgo实现定时检查大量的 CLOSE_WAIT 连接参考 go实现定时检查大量的 CLOSE_WAIT 连接 监控指定端口的连接状态&#xff0c;特别是关…

阿里云服务器公网带宽费用全解析(不同计费模式)

阿里云服务器公网带宽怎么收费&#xff1f;北京地域服务器按固定带宽计费一个月23元/M&#xff0c;按使用流量计费0.8元/GB&#xff0c;云服务器地域不同实际带宽价格也不同&#xff0c;阿里云服务器网aliyunfuwuqi.com分享不同带宽计费模式下带宽收费价格表&#xff1a; 公网…

了解 RISC-V IOMMU

了解 RISC-V IOMMU 个人作为 IOMMU 初学者&#xff0c;从初学者的角度介绍我眼中 RISCV 的 IOMMU 如果有些描述不够专业&#xff0c;还请谅解&#xff0c;也欢迎讨论 部分内容来自 https://zhuanlan.zhihu.com/p/679957276&#xff08;对于 RISCV IOMMU 规范手册的翻译&#xf…