JAVA:集合框架常见的面试题和答案

1、List接口的常见实现类有哪些?

答: 常见的List接口实现类包括:

  • ArrayList: 基于动态数组实现的List,支持快速随机访问。
  • LinkedList: 基于链表实现的List,支持快速的插入和删除操作。
  • Vector: 一个线程安全的动态数组,通常不建议使用,可以用ArrayList代替。
  • Stack: 继承自Vector,表示一个后进先出(LIFO)的堆栈。

2、ArrayList和LinkedList的区别是什么?

  • 数据结构实现:ArrayList :基于数组,便于按 index 访问,超过数组需要扩容,扩容成本较高。LinkedList:使用链表实现,无需扩容。
  • 随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
  • 增加和删除效率:在非首尾的增删操作,LinkedList 要比ArrayList 效率要高,因为ArrayList 增删操作要影响数组内的其他数据的下标。
  • 内存空间占用:LinkedList 比 ArrayList 更占内存,因为LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
  • 线程安全:ArrayList 和 LinkList 都是不同步的,不保证线程安全。
  • 综合来说,需要频繁读取集合中的元素时,更推荐使用 Arrayist,而在增删操作较多时,更推荐使用 LinkedList。
  • LinkedList 的双向链表是链表的一种,它的每个数据结点中都有2 个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便的访问它的前驱结点和后继结点。

3、Map接口的常见实现类有哪些?

答: 常见的Map接口实现类包括:

  • HashMap: 基于哈希表实现的Map,提供了快速的查找性能。
  • TreeMap: 基于红黑树实现的有序Map,按键的自然顺序或者定制的顺序进行排序。
  • LinkedHashMap: 基于哈希表和双向链表实现的Map,可以按照插入顺序或者访问顺序进行遍历。
  • Hashtable: 一个线程安全的哈希表,通常不建议使用,可以用HashMap代替。
  • ConcurrentHashMap: 一个线程安全的哈希表,支持并发操作。

4、HashTable,HashMap,TreeMap区别?

  • HashTable线程同步,HashMap,TreeMap非线程同步。
  • HashTable,TreeMap不允许<键,值>有空值,HashMap允许<键,值>有空值。
  • HashTable中hash数组的默认大小是11,增加方式的old*2+1,HashMap中hash数组的默认大小是16,增长方式一定是2的指数倍。
  • TreeMap能够把它保存的记录根据键排序,默认是按升序排序,因此如果你的键需要有序,建议使用TreeMap代替HashMap。

5、加载因子(扩容因子)为何默认是0.75?

  • 在空间占用与查询时间之间取得了较好的权衡
  • 大于这个值,空间节省了,但是链表可能过长就会影响性能
  • 小于这个值,冲突减少了,但是扩容就会比较频繁,空间占用多并且扩容也会消耗性能

6、LinkedHashMap的应用,底层,原理

答:LinkedHashMap维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序(insert-order)或者是访问顺序,其中默认的迭代访问顺序就是插入顺序,即可以按插入的顺序遍历元素,这点和HashMap有很大的不同。
LRU算法可以用LinkedHashMap实现。

7、HashMap 的底层数据结构是怎样的 ?

JDK1.8 之前

  • JDK1.8 之前 HashMap 底层是 数组和链表 结合在一起使用也就是链表散列。
  • HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到hash 值,然后通过(n-1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
  • 所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。

JDK1.8 之后

  • 当链表长度大于阈值(默认为 8)时,会首先调用 treeifyBin()方法。这个方法会根据HashMap 数组来决定是否转换为红黑树。只有当数组长度大于或者等于64的情况下,才会执行转换红黑树操作,以减少搜索时间。否则,就是只是执行resize() 方法对数组扩容。

8、HashMap 的扩容机制是怎样的?

一般情况下,当元素数量超过阈值时便会触发扩容。每次扩容的容量都是之前容量的2倍。HashMap 的容量是有上限的,必须小于 1<<30,即 1073741824。如果容量超出了这个数,则不再增长,且阈值会被设置为 Integer.MAX_VALUE。

JDK7 中的扩容机制

  • 空参数的构造函数:以默认容量、默认负载因子、默认阈值初始化数组。内部数组是空数组。
  • 有参构造函数:根据参数确定容量、负载因子、阈值等。
  • 第一次 put 时会初始化数组,其容量变为不小于指定容量的2 的幂数,然后根据负载因子确定阈值。
  • 如果不是第一次扩容,则 新容量=旧容量 x 2 ,新阈值=新容量x 负载因子。JDK8 的扩容机制
  • 空参数的构造函数:实例化的 HashMap 默认内部数组是null,即没有实例化。第一次调用 put 方法时,则会开始第一次初始化扩容,长度为 16。
  • 有参构造函数:用于指定容量。会根据指定的正整数找到不小于指定容量的2的幂数,将这个数设置赋值给阈值(threshold)。第一次调用 put 方法时,会将阈值赋值给容量,然后让 阈值 = 容量 x 负载因子。
  • 如果不是第一次扩容,则容量变为原来的 2 倍,阈值也变为原来的2 倍。(容量和阈值都变为原来的 2 倍时,负载因子还是不变)。
    此外还有几个细节需要注意:
  • 首次 put 时,先会触发扩容(算是初始化),然后存入数据,然后判断是否需要扩容;
  • 不是首次 put,则不再初始化,直接存入数据,然后判断是否需要扩容;

9、ConcurrentHashMap 的存储结构是怎样的?

  • Java7 中 ConcurrnetHashMap 使用的分段锁,也就是每一个Segment 上同时只有一个线程可以操作,每一个 Segment 都是一个类似 HashMap 数组的结构,它可以扩容,它的冲突会转化为链表。但是 Segment 的个数一但初始化就不能改变,默认Segment的个数是 16 个。
  • Java8 中的 ConcurrnetHashMap 使用的 Synchronized 锁加CAS 的机制。结构也由Java7 中的 Segment 数组 + HashEntry 数组 + 链表 进化成了Node 数组+链表/红黑树,Node 是类似于一个 HashEntry 的结构。它的冲突再达到一定大小时会转化成红黑树,在冲突小于一定数量时又退回链表。

10、用过 ConcurrentHashMap,讲一下他和HashTable 的不同之处?

  • HashTable 就是实现了 HashMap 加上了 synchronized,而ConcurrentHashMap底层采用分段的数组+链表实现,线程安全
  • ConcurrentHashMap 通过把整个 Map 分为 N 个 Segment,可以提供相同的线程安全,但是效率提升 N 倍,默认提升 16 倍。
  • 并且读操作不加锁,由于 HashEntry 的 value 变量是 volatile 的,也能保证读取到最新的值。
  • Hashtable 的 synchronized 是针对整张 Hash 表的,即每次锁住整张表让线程独占,ConcurrentHashMap 允许多个修改操作并发进行,其关键在于使用了锁分离技术
  • 扩容:段内扩容(段内元素超过该段对应 Entry 数组长度的75%触发扩容,不会对整个Map 进行扩容),插入前检测需不需要扩容,有效避免无效扩容

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

  • HashSet 是 Set 接口的主要实现类 ,HashSet 的底层是HashMap,线程不安全的,可以存储 null 值;
  • LinkedHashSet 是 HashSet 的子类,能够按照添加的顺序遍历;
  • TreeSet 底层使用红黑树,元素是有序的,排序的方式有自然排序和定制排序。

12、Comparable 和 Comparator 的区别?

  • comparable 接口实际上是出自 java.lang 包 它有一个 compareTo(Object obj)方法用来排序
  • comparator 接口实际上是出自 java.util 包它有一个 compare(Object obj1, Objectobj2)方法用来排序
    一般我们需要对一个集合使用自定义排序时,我们就要重写compareTo()方法或compare()方法,当我们需要对某一个集合实现两种排序方式,比如一个song对象中的歌名和歌手名分别采用一种排序方法的话,我们可以重写 compareTo()方法和使用自制的Comparator 方法或者以两个 Comparator 来实现歌名排序和歌星名排序,第二种代表我们只能使用两个参数版的 Collections.sort()。

13、什么是哈希冲突?

答:当两个不同的输入值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)。

14、CopyOnWriteArrayList与ArrayList、Vector的区别

答:CopyOnWriteArrayList与ArrayList、Vector有以下主要区别:

  • 线程安全性:CopyOnWriteArrayList是线程安全的,而ArrayList不是;Vector也是线程安全的,但它使用全局锁,导致性能较差。
  • 读写性能:CopyOnWriteArrayList具有较高的并发读性能,但写操作性能较差,因为每次写操作都需要复制一个新的副本。ArrayList具有较高的读写性能,但在多线程环境下可能出现线程安全问题。Vector的读写性能较差,因为它使用全局锁。
  • 内存占用:CopyOnWriteArrayList在写操作时需要复制一个新的副本,因此可能导致较高的内存占用。ArrayList和Vector的内存占用相对较低。
  • 实时性:CopyOnWriteArrayList的迭代器只能获取到写操作前的数据副本,因此在迭代过程中无法获取实时数据。ArrayList和Vector的迭代器可以获取实时数据,但在多线程环境下可能会导致线程安全问题。

15、如何将Map转换为List?

答: 可以使用ArrayList的构造函数或者addAll方法将Map转换为List。

使用构造函数:

List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());

使用addAll方法:

List<Map.Entry<K, V>> list = new ArrayList<>();
list.addAll(map.entrySet());

16、LinkedHashSet和CopyOnWriteArraySet的区别

答:LinkedHashSet和CopyOnWriteArraySet是Java集合框架中不同的实现类,它们具有不同的特性和适用场景。

LinkedHashSet:

  • 内部实现:
    LinkedHashSet 是基于哈希表和双向链表实现的,它继承自HashSet,保留了元素插入的顺序。
  • 有序性:
    LinkedHashSet 保持了元素插入的顺序,因此可以按照插入顺序进行遍历。
  • 性能:
    由于它的底层实现依赖于哈希表,因此查找元素的速度非常快。
  • 线程安全:
    LinkedHashSet 是非线程安全的。
  • 适用场景:
    当你需要保留元素插入的顺序,并且不需要考虑线程安全时,可以使用LinkedHashSet。

CopyOnWriteArraySet:

  • 内部实现:
    CopyOnWriteArraySet 是基于CopyOnWriteArrayList实现的,它是一个线程安全的Set。
  • 线程安全:
    CopyOnWriteArraySet 是线程安全的,它的所有修改操作都是在一个新的副本上进行的,而不会影响原始集合。
  • 写时复制:
    当需要对集合进行修改时,CopyOnWriteArraySet 会先复制一个新的数组,然后在新的数组上进行修改,最后将新的数组替换原始数组。
  • 适用场景:
    当你需要在多线程环境下保证安全地对集合进行修改时,可以使用CopyOnWriteArraySet。它适用于读多写少的场景。

17、Java中Queue接口的常见实现类有哪些?

答: 常见的Queue接口实现类包括LinkedList、PriorityQueue和ArrayDeque。

18、LinkedList和ArrayDeque之间有什么区别?

  • LinkedList 是一个双向链表实现的队列,可以作为队列和双端队列使用。
  • ArrayDeque 是一个基于动态数组实现的双端队列,它的性能比LinkedList稍好,但不支持索引访问。

19、PriorityQueue是什么?它是如何工作的?

答: PriorityQueue 是一个优先级队列,它根据元素的优先级来确定出队顺序。默认情况下,PriorityQueue 是一个最小堆实现,可以通过提供一个自定义的Comparator来实现最大堆。

20、队列和栈有什么区别?

  • 队列是一种先进先出(FIFO)的数据结构,只允许在队列的一端插入元素,在另一端删除元素。
  • 栈是一种后进先出(LIFO)的数据结构,只允许在栈的一端插入和删除元素。

21、如何在多线程环境中使用BlockingQueue?

答案: 可以通过创建一个BlockingQueue实例,然后在生产者线程中使用put方法向队列中添加元素,在消费者线程中使用take方法获取元素。

BlockingQueue<ElementType> queue = new LinkedBlockingQueue<>();
// 生产者线程
queue.put(element);
// 消费者线程
ElementType element = queue.take();

22、ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?

  • ConcurrentLinkedQueue 是一个基于非阻塞算法实现的非阻塞队列,它在高并发环境下表现良好。
  • LinkedBlockingQueue 是一个基于锁实现的阻塞队列,它可以在队列为空或者满时阻塞线程。

23、如何实现一个自定义的优先级队列?

答案: 可以使用PriorityQueue并提供一个自定义的比较器(Comparator)来实现一个自定义的优先级队列。

PriorityQueue<Element> priorityQueue = new PriorityQueue<>(new MyComparator()

24、ArrayBlockingQueue和LinkedBlockingQueue的区别

答:ArrayBlockingQueue和LinkedBlockingQueue是Java中两种不同类型的阻塞队列实现,它们有一些重要的区别。

ArrayBlockingQueue:

  • 内部实现:
    ArrayBlockingQueue 是一个基于数组实现的有界阻塞队列,它按照先进先出(FIFO)的原则对元素进行排序。
  • 容量限制:
    ArrayBlockingQueue 在创建时需要指定一个固定的容量,即队列中可以存放的最大元素数量。
  • 阻塞特性:
    当队列已满时,ArrayBlockingQueue 会阻塞等待直到有空间可以放置新元素。
    当队列为空时,尝试从中获取元素的操作会被阻塞等待,直到队列中有新的元素。
  • 性能:
    由于底层是基于数组实现的,因此在性能上比LinkedBlockingQueue更高效,但它的容量是固定的。

LinkedBlockingQueue:

  • 内部实现:
    LinkedBlockingQueue 是一个基于链表实现的无界阻塞队列,它按照先进先出(FIFO)的原则对元素进行排序。
  • 容量限制:
    LinkedBlockingQueue 的容量理论上可以是无限大,因此它不会因为达到最大容量而阻塞。
  • 阻塞特性:
    当队列为空时,尝试从中获取元素的操作会被阻塞等待,直到队列中有新的元素。
    当队列已满时,LinkedBlockingQueue 会阻塞等待直到有空间可以放置新元素。
  • 性能:
    由于底层是基于链表实现的,相对于ArrayBlockingQueue来说,它在高并发场景下可能会略显低效。
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【开源】基于SpringBoot的天然气工程业务管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、使用角色3.1 施工人员3.2 管理员 四、数据库设计4.1 用户表4.2 分公司表4.3 角色表4.4 数据字典表4.5 工程项目表4.6 使用材料表4.7 使用材料领用表4.8 整体E-R图 五、系统展示六、核心代码6.1 查询工程项目6.2 工程物资…

泛积木-低代码 使用攻略

文档首发于 泛积木-低代码 使用攻略 我们以大纲的方式&#xff08;总体把握&#xff09;讲述如何高效、便捷使用 泛积木-低代码。 权限 首先说下权限&#xff0c;在 系统设置 / 权限设置 菜单内&#xff0c;我们可以新增调整项目内的权限&#xff0c;默认拥有管理员和成员两…

Python数据挖掘:入门、进阶与实用案例分析——基于非侵入式负荷检测与分解的电力数据挖掘

文章目录 摘要01 案例背景02 分析目标03 分析过程04 数据准备05 属性构造06 模型训练07 性能度量08 推荐阅读赠书活动 摘要 本案例将根据已收集到的电力数据&#xff0c;深度挖掘各电力设备的电流、电压和功率等情况&#xff0c;分析各电力设备的实际用电量&#xff0c;进而为电…

仓库管理系统源代码集合,带图片展示和网站演示

目录 1、ModernWMS2、GreaterWMS3、kopSoftWMS4、SwebWMS5、若依wms6、jeewms 1、ModernWMS 体验地址&#xff1a;https://wmsonline.ikeyly.com 简易完整的仓库管理系统 该库存管理系统是&#xff0c;我们从多年ERP系统研发中总结出来的一套针对小型物流仓储供应链流程。 简…

《C和指针》笔记34:字符串函数

文章目录 1. 获取字符串长度strlen 2. 复制字符串strcpystrncpy 3. 拼接字符串strcatstrncat 4. 字符串比较strcmpstrncmp 5. 查找字符strchr和strrchr&#xff1a;查找一个字符strpbrk&#xff1a;查找任何几个字符strstr&#xff1a;查找一个子串strspn和strcspn&#xff1a;…

Nginx的进程结构实例演示

可以参考《Ubuntu 20.04使用源码安装nginx 1.14.0》安装nginx 1.14.0。 nginx.conf文件中worker_processes 2;这条语句表明启动两个worker进程。 sudo /nginx/sbin/nginx -c /nginx/conf/nginx.conf开启nginx。 ps -ef | grep nginx看一下进程情况。 sudo /nginx/sbin/ng…

Mathtype使用指南01:下载与安装

目录 介绍&#xff1a; 安装 介绍&#xff1a; MathType 是一款广泛用于数学和科学文档创建的强大数学编辑工具。它允许用户轻松地在各种文档类型中插入数学方程、符号和公式&#xff0c;是学术界、工程领域、出版界和教育机构中的专业人士常用的工具。下面是关于 MathType 的…

设计模式:桥接模式(C#、JAVA、JavaScript、C++、Python、Go、PHP)

上一篇《适配器模式》 下一篇《装饰器模式》 简介&#xff1a; 桥接模式&#xff0c;它是一种结构型设计模式&#xff0c;它的主要目的是将抽象部分与具体实现部分分离&#xff0c;使它们都可以独立地变化。…

SQL server 代理服务启动和查看

设置重启 使用管理员权限登录到运行 SQL Server 代理服务的计算机。 打开 Windows 服务管理器。可以通过按下 Windows 键 R&#xff0c;然后键入 "services.msc" 并按 Enter 来打开服务管理器。 在服务列表中&#xff0c;找到 "SQL Server Agent" 服务&…

网络协议--TFTP:简单文件传送协议

15.1 引言 TFTP(Trivial File Transfer Protocol)即简单文件传送协议&#xff0c;最初打算用于引导无盘系统&#xff08;通常是工作站或X终端&#xff09;。和将在第27章介绍的使用TCP的文件传送协议&#xff08;FTP&#xff09;不同&#xff0c;为了保持简单和短小&#xff0…

无需更换vue-cli 脚手架 uniapp-搭建项目-H5-低版本安卓IOS兼容问题(白屏)(接口请求异常)

✨求关注~ &#x1f4bb;博客&#xff1a;www.protaos.com I. 简介 A. UniApp项目概述 B. 白屏和接口请求异常问题的背景 II. 白屏问题 A. 问题描述 1、uniapp 打包H5内嵌入APP内、低版本手机系统访问白屏问题 B. 问题根本原因 1、低版本手机系统 自带的webview内核不支持ES6语…

Java练习题2020-4

小明今天收了N个鸡蛋&#xff0c;每个鸡蛋各有重量&#xff0c;现在小明想找M个重量差距最小的鸡蛋摆成一盒出售&#xff0c;输出符合条件的最重一盒鸡蛋的总重量 输入说明&#xff1a;第一行&#xff0c;鸡蛋个数N(N<1000) 每盒个数M(M<N)&#xff1b;第二行&#xff0…

Jtti:Apache服务的反向代理及负载均衡怎么配置

配置Apache服务的反向代理和负载均衡可以帮助您分散负载并提高应用程序的可用性和性能。下面是一些通用的步骤&#xff0c;以配置Apache反向代理和负载均衡。 1. 安装和配置Apache&#xff1a; 确保您已经安装了Apache HTTP服务器。通常&#xff0c;Apache的配置文件位于/etc…

Linux进程控制(一)

前言&#xff1a;Linux进程控制是指在Linux操作系统中&#xff0c;对进程的创建、运行、管理和终止等方面进行控制的一系列机制和技术。Linux作为一个多任务操作系统&#xff0c;能够同时运行多个进程任务的执行&#xff0c;继前面我们对Linux进程创建的学习之后&#xff0c;今…

CSP-J 2023 第二轮认证入门级(含答案)

一。题目 二。答案 T1 ⼩苹果&#xff08;apple&#xff09; 每⼀轮拿掉的苹果数量为 。模拟拿苹果的过程&#xff0c;每⼀轮中令 &#xff0c;当 时最后⼀个苹果会被拿掉。 时间复杂度为对数。 #include <iostream> using namespace std; int n; int ans1, ans2; boo…

上海高考语文命题趋势和备考建议?附1990年-2023年高考语文真题和答案资源

虽然语文是我们的母语&#xff0c;但是语文从小到大都是我们学习的重点&#xff0c;更是难点&#xff0c;分值也是最高的科目之一。甚至很多时候&#xff0c;语文科目的分值差会带来最终的分值差。综观各个省市的高考状元&#xff0c;基本上语文科目都在130分以上&#xff08;满…

【DOCKER】

Docker 出现&#xff1a; 解决了运行环境和配置问题的软件容器。 方便做持续集成并有助于整体发布的容器虚拟化技术。 面试题&#xff1a; 容器和虚拟机比较&#xff1f; 区别&#xff1a; 1.Docker的三件套 1.镜像&#xff1a; 2.容器 3.仓库 2. 基础架构图 2.…

JavaScript_Pig Game切换当前玩家

const current0El document.getElementById(current--0); const current1El document.getElementById(current--1); if (dice ! 1) {currentScore dice;current0El.textContent currentScore;} else {} });这是我们上个文章写的代码&#xff0c;这个代码明显是有问题的&…

【爬虫】python打包可执行程序(ui界面制作完成后)

1.安装pyinstaller pip install pyinstaller可能出现连接超时安装不上的情况,可以切换源进行下载 pip install -i http://pypi.douban.com/simple/ pyinstaller2.打包程序 pyinstaller xxxxx.py --noconsole --hidden-import PySide6.QtXml

基于非侵入式负荷检测与分解的电力数据挖掘

基于非侵入式负荷检测与分解的电力数据挖掘 在这里插入图片描述 **摘要&#xff1a;本案例将根据已收集到的电力数据&#xff0c;深度挖掘各电力设备的电流、电压和功率等情况&#xff0c;分析各电力设备的实际用电量&#xff0c;进而为电力公司制定电能能源策略提供一定的参…
最新文章