当前位置: 首页 > news >正文

Java面试——集合篇

1.Java中常用的容器有哪些?

容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表。

如图:

面试官追问:说说集合有哪些类及他们各自的区别和特点?

  • Set(所有实现类都不支持重复的元素)
    • TreeSet 基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN)。
    • HashSet 基于HashMap实现,HashSet 的每个元素实际上是 HashMap 的一个键,而对应的值(value)是一个固定的虚拟对象。支持快速查找,但不支持有序性操作。并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的。
    • LinkedHashSet 是 HashSet 的子类,并且其内部是通过 LinkedHashMap 来实现的。内部使用双向链表维护元素的插入顺序。
  • List
    • ArrayList 基于动态数组实现,支持随机访问。
    • Vector 和 ArrayList 类似,但它是线程安全的,底层方法用synchronized修饰。
    • LinkedList 基于双向链表实现,只能顺序访问,但是可以快速地在链表中间插入和删除元素。不仅如此,LinkedList 还可以用作栈、队列和双向队列。
  • Queue
    • LinkedList 可以用它来实现双向队列。
    • PriorityQueue 基于堆结构实现,可以用它来实现优先队列。
    • ArrayQueue基于数组实现,可以用它实现双端队列,也可以作为栈。

面试官追问:说说Map有哪些类及他们各自的区别和特点?

  • TreeMap 基于红黑树实现。
  • HashMap 1.7基于数组+链表实现,1.8基于数组+链表+红黑树。链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突)。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
  • HashTable 和 HashMap 类似,但它是线程安全的,这意味着同一时刻多个线程可以同时写入 HashTable 并且不会导致数据不一致。它是遗留类,不应该去使用它。(现在可以使用 ConcurrentHashMap 来支持线程安全,并且 ConcurrentHashMap 的效率会更高(1.7 ConcurrentHashMap 引入了分段锁, 1.8 引入了红黑树)。)
  • LinkedHashMap继承自 HashMap。使用双向链表来维护元素的顺序,顺序为插入顺序或者最近最少使用(LRU)顺序。

2. Arraylist 和 LinkedList的区别?

  • ArrayList:底层是基于数组实现的,查找快,增删较慢LinkedList 不支持高效的随机元素访问,而 ArrayList 支持。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。
  • LinkedList:底层是基于链表实现的。确切的说是循环双向链表(JDK1.6之前是双向循环链表、JDK1.7之后取消了循环),查找慢、增删快。LinkedList链表由一系列表项连接而成,一个表项包含3个部分︰元素内容、前驱表和后驱表。因此内存空间占用比ArrayList 更多。

面试官追问:ArrayList的增删一定比LinkedList要慢吗?

不一定的。

  1. 如果增删都是在末尾来操作(每次调用的都是 remove() 和 add()),此时 ArrayList就不需要移动和复制数组来进行操作了。如果数据量有百万级的时,速度是会比 LinkedList 要快的。
  2. 如果删除操作的位置是在中间。由于LinkedList的消耗主要是在遍历上,ArrayList的消耗主要是在移动和复制上(底层调用的是arrayCopy()方法,是native方法)。LinkedList 的遍历速度是要慢于ArrayList的复制移动速度的。如果数据量有百万级的时,还是ArrayList要快。

3.ArrayList实现 RandomAccess接口有何作用?

查看源码我们发现实际上 RandomAccess 接口中什么都没有定义。

        从源码可以看出RandomAccess 接口只是一个标志接口,只要List集合实现这个接口,就能支持快速随机访问。通过查看Collections类中的binarySearch()方法,可以看出,判断List是否实现RandomAccess接口来实行indexedBinarySerach(list, key)或 iteratorBinarySerach(list, key)方法。再通过查看这两个方法的源码发现:实现RandomAccess接口的List集合采用一般的 for循环遍历,而未实现这接口则采用迭代器,即ArrayList 一般采用for循环遍历,而 LinkedList 一般采用迭代器遍历。

public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)return Collections.indexedBinarySearch(list, key);elsereturn Collections.iteratorBinarySearch(list, key);
}

面试官追问:为何LinkedList却没实现这个接口?

ArrayList 底层是数组,而 LinkedList 底层是链表。

数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。

ArrayList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能。 RandomAccess 接口只是标识,并不是说 ArrayList 实现 RandomAccess 接口才具有快速随机访问功能的!


4.Vector 和 ArrayList 的区别?

他们两个都实现了List接口。底层数据结构都是数组。

不同的是:

  1. vector通过removeadd等方法加上synchronized关键字实现线程同步,所以是线程安全的。而ArrayList是线程不安全的
  2. 由于vector使用了synchronized进行加锁,所以性能不如ArrayList
  3. Vector 扩容时,如果未指定扩容递增值capacityIncrement,或该值不大于 0 时,每次扩容为原来的 2 倍,否则扩容量为capacityIncrement的值。ArrayList每次扩容为旧容量的1.5

5. ArrayList 的扩容机制?

第一种情况:list中第一次添加数据

1585c2a5193a4e44b6ea83fbdbebc371.png

这种情况下,因为DEFAULT_CAPACITY = 10; 默认初始的容量(CAPACITY)

所以minCapacity会被赋值为较大的那个,也就是10。所以这里需要扩容(minCapacity(10) - elementData.length(0) > 0)进入扩容方法。

而进入扩容方法以后,会走第一次初始化数组长度那个if判断。

第二种情况:添加数据,但不需要扩容

3212cc99a561493a9f091f9b236c0463.png

这种情况下,根本不会走到扩容方法。

第三种情况:本次添加数据又需要扩容了

d829a3a2608c4ef1abfefe61971bfc15.png

这种情况下,进入扩容方法以后,会扩容原来容量的1.5倍。最后还会进行数组拷贝,把原数组元素拷贝到,新增容量后的数组中!

总结:

  1. 当使用add方法的时候首先调用ensureCapacityInternal方法,传入 size+1进去,检查是否需要扩容

  2. 如果空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,就初始化为默认大小10,获取“默认的容量”和要扩容的大小两者之间的最大值

  3. 和当前数组长度比较,如果 if (minCapacity - elementData.length > 0)执行grow扩容方法

  4. 将数组扩容为原来的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1);

  5. 检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量

  6. 再检查新容量newCapacity 是否超出了ArrayList所定义的最大容量,若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE,如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Interger.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE(MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8

  7. ArrayList 中copy数组的核心就是System.arraycopy方法,将original数组的所有数据复制到copy数组中,这是一个本地方法


6.Array和ArrayList有何区别?

  • Array(就是数组)可以容纳基本类型和对象,而ArrayList(集合)只能容纳对象
  • Array是指定大小的,ArrayList 的容量是根据需求自动扩展
  • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等

面试官追问:什么时候更适合使用Array?

  1. 如果列表的大小已经指定,大部分情况下是存储和遍历它们可以使用Array
  2. 对于基本类型数据,ArrayList 使用自动装箱来减少编码工作量;而当处理固定大小的基本数据类型的时候,这种方式相对比较慢,这时候应该使用Array
  3. 如果你要使用多维数组,使用[][]比 List更容易

7.comparable和comparator的区别?

  • comparable接口出自java.lang包,可以理解为一个内比较器,因为实现了comparable接口的类可以和自己比较,要和其他实现了Comparable接口类比较,可以使用compareTo(objectobj)方法。compareTo方法的返回值是int,有三种情况:
    1. 返回正整数(比较者大于被比较者)
    2. 返回0(比较者等于被比较者)
    3. 返回负整数(比较者小于被比较者)
  • comparator接口出自java.util包,它有一个compare(object obj1,object obj2)方法用来排序,返回值同样是int,有三种情况,和compareTo类似。

它们之间的区别:

  1. 很多包装类都实现了comparable接口,像Integer、string等。所以直接调用co1lections.sort()直接可以使用。如果对类里面自带的自然排序不满意,而又不能修改其源代码的情况下,使用comparator就比较合适。
  2. 此外使用comparator可以避免添加额外的代码与我们的目标类耦合,同时可以定义多种排序规则,这一点是comparable接口没法做到的
  3. 从灵活性和扩展性讲Comparator更优,故在面对自定义排序的需求时,可以优先考虑使用comparator接口。

详细讲解:面试官:元素排序Comparable和Comparator有什么区别?-CSDN博客


8.Collection和Collections有什么区别?

  • Collection:是最基本的集合接口,它提供了对集合对象进行基本操作的通用接口方法。一个Collection代表一组Object,即Collection的元素。它的直接继承接口有List,Set 和Queue。
  • Collections:是不属于Java的集合框架的,它是集合类的一个工具类此类不能被实例化服务于Java的Collection框架。它包含有关集合操作的静态多态方法,实现对各种集合的搜索、排序、线程安全等操作。

相关文章:

Java面试——集合篇

1.Java中常用的容器有哪些&#xff1f; 容器主要包括 Collection 和 Map 两种&#xff0c;Collection 存储着对象的集合&#xff0c;而 Map 存储着键值对(两个对象)的映射表。 如图&#xff1a; 面试官追问&#xff1a;说说集合有哪些类及他们各自的区别和特点&#xff1f; S…...

算法【双向广搜】

双向广搜常见用途 1&#xff1a;小优化。bfs的剪枝策略&#xff0c;分两侧展开分支&#xff0c;哪侧数量少就从哪侧展开。 2&#xff1a;用于解决特征很明显的一类问题。特征&#xff1a;全量样本不允许递归完全展开&#xff0c;但是半量样本可以完全展开。过程&#xff1a;把…...

javascript检测数据类型的方法

1. typeof 运算符 typeof是一个用来检测变量的基本数据类型的运算符。它可以返回以下几种类型的字符串&#xff1a;“undefined”、“boolean”、“number”、“string”、“object”、“function” 和 “symbol”&#xff08;ES6&#xff09;。需要注意的是&#xff0c;对于 n…...

生信初学者教程(五):R语言基础

文章目录 数据类型整型逻辑型字符型日期型数值型复杂数数据结构向量矩阵数组列表因子数据框ts特殊值缺失值 (NA)无穷大 (Inf)非数字 (NaN)安装R包学习材料R语言是一种用于统计计算和图形展示的编程语言和软件环境,广泛应用于数据分析、统计建模和数据可视化。1991年:R语言的最…...

深度学习计算

一、层和块 块可以描述单个层、多个层组成的组件或整个模型。 通过定义块&#xff0c;组装块&#xff0c;可以实现复杂的神经网络。 一个块可以由多个class组成。 其实就是 自己定义神经网络net&#xff0c;自己定义层的顺序和具体的init、 forward函数。 层和块的顺序由sequen…...

Hexo博客私有部署Twikoo评论系统并迁移评论记录(自定义邮件回复模板)

部署 之前一直使用的artalk&#xff0c;现在想改用Twikoo&#xff0c;采用私有部署的方式。 私有部署 (Docker) 端口可以根据实际情况进行修改 docker run --name twikoo -e TWIKOO_THROTTLE1000 -p 8100:8100 -v ${PWD}/data:/app/data -e TWIKOO_PORT8100 -d imaegoo/twi…...

Vue.js 与 Flask/Django 后端配合:构建现代 Web 应用的最佳实践

Vue.js 与 Flask/Django 后端配合&#xff1a;构建现代 Web 应用的最佳实践 在现代 Web 开发中&#xff0c;前后端分离的架构已经成为主流。Vue.js 作为一个渐进式 JavaScript 框架&#xff0c;因其灵活性和易用性而广受欢迎。而 Flask 和 Django 则是 Python 生态中两个非常流…...

【笔记】自动驾驶预测与决策规划_Part3_路径与轨迹规划

文章目录 0. 前言1. 基于搜索的路径规划1.1 A* 算法1.2 Hybrid A* 算法 2. 基于采样的路径规划2.1 Frent Frame方法2.2 Cartesian →Frent 1D ( x , y ) (x, y) (x,y) —> ( s , l ) (s, l) (s,l)2.3 Cartesian →Frent 3D2.4 贝尔曼Bellman最优性原理2.5 高速轨迹采样——…...

Shiro-721—漏洞分析(CVE-2019-12422)

文章目录 Padding Oracle Attack 原理PKCS5填充怎么爆破攻击 漏洞原理源码分析漏洞复现 本文基于shiro550漏洞基础上分析&#xff0c;建议先看上期内容&#xff1a; https://blog.csdn.net/weixin_60521036/article/details/142373353 Padding Oracle Attack 原理 网上看了很多…...

【Python语言初识(一)】

一、python简史 1.1、python的历史 1989年圣诞节&#xff1a;Guido von Rossum开始写Python语言的编译器。1991年2月&#xff1a;第一个Python编译器&#xff08;同时也是解释器&#xff09;诞生&#xff0c;它是用C语言实现的&#xff08;后面&#xff09;&#xff0c;可以调…...

Python 中的方法解析顺序(MRO)

在 Python 中&#xff0c;MRO&#xff08;Method Resolution Order&#xff0c;方法解析顺序&#xff09;是指类继承体系中&#xff0c;Python 如何确定在调用方法时的解析顺序。MRO 决定了在多继承环境下&#xff0c;Python 如何寻找方法或属性&#xff0c;即它会根据一定规则…...

MySQL表的内外连接

内连接 其实就是from 两个表 把笛卡尔积的表 再用where 进行条件筛选 ——之前我们写的多表查询就是内连接 基本格式&#xff1a; 外链接 没有向内连接那样真的把两个表连接形式一个表显示&#xff0c;而只是建立关系 外连接分为左链接和右链接 左链接 联合查询时候&#…...

系统架构设计师:软件架构的演化和维护

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师:软件架构的演化和维护前言软件架构演化的重要性面向对象的软件架构演…...

QT的dropEvent函数进入不了

在使用QT想实现拖拽功能的时候&#xff0c;发现了dropEvent没有调用运行&#xff0c;遂查找原因&#xff1a; 首先是网上都说要在dragEnterEvent里面使用event->accept(); 但我这边在出现问题之前就已经这样做了&#xff1a; void CanvasView::dragEnterEvent(QDragEnterEv…...

Spring Boot 入门

前言 Spring Boot 是一个开源的 Java 基础框架&#xff0c;用于创建独立、生产级的基于 Spring 的应用程序。它简化了基于 Spring 的应用开发&#xff0c;通过提供一系列的“起步依赖”来快速启动和运行 Spring 应用。本文将带你深入了解 Spring Boot 的核心概念、关键特性&am…...

LDD学习2--Scull(TODO)

《Linux Device Drivers》&#xff08;LDD&#xff09;书籍中的 scull&#xff08;Simple Character Utility for Loading Localities&#xff09;是一个用于演示 Linux 字符设备驱动程序编写的示例代码。它为理解 Linux 内核模块和字符设备驱动程序的编写提供了基础实践平台&a…...

【算法-堆排序】

堆排序是一种基于堆这种数据结构的比较排序算法&#xff0c;它是一种原地、不稳定的排序算法&#xff0c;时间复杂度为 O(n log n)。堆排序的基本思想是将数组构建成一个二叉堆&#xff0c;并通过反复调整堆顶和未排序部分之间的关系来实现排序。 堆的定义 堆是一种特殊的完全…...

音视频入门基础:AAC专题(4)——ADTS格式的AAC裸流实例分析

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…...

【第33章】Spring Cloud之SkyWalking服务链路追踪

文章目录 前言一、介绍1. 架构图2. SkyWalking APM 二、服务端和控制台1. 下载2. 解压3. 初始化数据库4. 增加驱动5. 修改后端配置6. 启动7. 访问控制台8. 数据库表 三、客户端1. 下载2. 设置java代理3. idea配置3.1 环境变量3.2 JVM参数3.3 启动日志 4. 启用网关插件 四、链路…...

如何选择OS--Linux不同Distribution的选用

写在前言&#xff1a; 刚写了Windows PC的不同editions的选用&#xff0c;趁热&#xff0c;把Linux不同的Distribution选用也介绍下&#xff0c;希望童鞋们可以了解-->理解-->深入了解-->深入理解--...以致于能掌握特定版本的Linux的使用甚者精通。……^.^…… so&a…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...