java面试题(常见集合)

算法复杂度分析

时间复杂度分析

时间复杂度分析:来评估代码的执行耗时的
大O表示法:不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势

空间复杂度

空间复杂度的全称是渐进空间复杂度,表示算法占用的额外存储空间和数据规模之间的增长关系

数组

数组(Array)是一种用连续的内存空间存储相同数据类型数据的线性数据结构

数组如何获取其他元素的地址值

寻址公式:a[i] = baseAddress + i * dataTypeSize
baseAddrss:数组的首地址
dataTypeSize:代表数组中元素类型的大小,int刑的数组,dataTypeSize=4个字节

为什么数组索引从0开始,而不是1

寻址公式:a[i] = baseAddress + (i-1) * dataTypeSize
此公式对cpu来说就多了一次减法指令,性能不如从0开始

操作数组的时间复杂度

查找

  1. 随机查询(根据索引查询):数据元素的访问是通过下标来访问的,计算机通过数组的首地址和寻址公式能欧很快速的找到想要访问的元素(O(1))
  2. 未知索引查询
    情况一:查找数组内的元素(O(n))
    情况二:查找排序后数组内的元素(O(logn))

插入/删除

数组是一段连续的内存空间,因此为了保证数组的连续性会使得数组的插入和删除的效率变得很低
最好的情况下是O(1),最坏的情况下是O(n),平均情况下的时间复杂度是O(n)

ArrayList

成员变量

在这里插入图片描述

构造方法

在这里插入图片描述
在这里插入图片描述

添加和扩容操作

如果空间够就直接添加,不够的话就扩容后拷贝数组再添加

实现原理

  1. ArrayList底层是用动态的数组实现的
  2. ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10
  3. ArrayList在进行扩容的时候时原来容量的1.5倍,每次扩容都需要拷贝数组
  4. ArrayList在添加数据的时候
    1. 确保数组已使用长度(size)加1之后足够存下下一个数据
    2. 计算数组的容量,如果当前数组已使用长度+1后的大于当前数组长度,则调用grow方法扩容(原来的1.5倍)
    3. 确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上
    4. 返回添加成功布尔值

如何实现数组和List之间的转换

数组转换成List:Arrays.asList(Array),修改原数组会收到影响,因为这个方法没有创建新对象,只是引用了地址
List转换为数组:list.toArray(new String[list.size()])

单向链表

  1. 链表中的每一个元素称之为节点(Node)
  2. 物理存储单元上,非连续,非顺序的存储结构
  3. 单向链表:每个节点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个节点地址的指针域。记录下个节点地址的指针叫做后续指针

查询

  1. 只有在查询头节点的时候不需要遍历链表,时间复杂度是O(1)
  2. 查询其他节点需要遍历链表,时间复杂度时O(n)

删除

  1. 只有在删除头节点的时候不需要遍历链表,时间复杂度是O(1)
  2. 删除其他节点需要遍历链表,时间复杂度时O(n)

双向链表

顾名思义,它支持两个方向

  1. 每个节点不止有一个后继指针next指向后面的节点,有一个前驱指针prev指向前面的节点
    对比单链表
    1. 双向链表需要额外的两个空间来存储后继节点和前驱节点的地址
    2. 支持双向遍历,这样也带来了双向链表操作的灵活性

ArrayList与LinkedList

  1. 底层数据结构
    1. ArrayList是动态数组的数据结构实现
    2. LinkedList是双向链表的数据结构实现
  2. 操作数据效率
    1. ArrayList按照下表查询的时间复杂度O(1)【内存是连续的,根据寻址公式】,LinkedList不支持下标查询
    2. 查询(未知索引):ArrayList需要遍历,链表也需要遍历,时间复杂度都是O(n)
    3. 新增和删除
      1. ArrayList尾部插入和删除是O(1);其他部分是O(n)
      2. LinkedList头尾节点删除时间复杂度是O(1);其他部分是O(n)
  3. 内存空间占用
    1. ArrayList底层是数组,内存连续,节省内存
    2. LinkedList是双向链表需要存储数据,和两个指针,更占用内存
  4. 线程安全
    1. 都不线程安全
    2. 解决方案:
      1. 在方法内使用,局部变量是安全的
      2. 使用线程全的ArrayList和LinkedList
      3. List<Object> syncArrayList = Collections.synchronizedList(new ArrayList<>())

HashMap

二叉树

二叉树,每个节点最多有两个叉,也就是两个子节点,分别是左子节点和右子节点,不过,二叉树并不要求每个节点都有两个子节点,有的只有左子节点,有的只有右子节点
二叉树的每个左子树和右子树也分别满足二叉树的定义
Java中有两个方式可以实现二叉树:数组存储,链式存储
基于链式存储的数的节点可定义如下:

private class TreeNode{
	int val;
	TreeNode left;
	TreeNode right;
	Treenode(){}
	Treenode(int val){this.val = val}
	Treenode(int val,TreeNode left,TreeNode right){
		this.val = val;
		this.left = left;
		this.right = right;
	}
}

二叉搜索树

二叉搜索树(Binary Search Tree,BST)右名二叉查找树,有序二叉树或者排序二叉树,是二叉树中比较常用的一种类型,二叉查找树要求,在数中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值
插入,查找,删除的时间复杂度O(logn)

红黑树

红黑树(Red Black Tree):也是一种自平衡的二叉搜索树(BST),之前叫做平衡二叉B树(Symmetric Binary B-Tree)

红黑树的特质

  1. 节点要么是红色要么是黑色
  2. 根节点是黑色
  3. 叶子节点都是黑色的空节点
  4. 红黑树中红色节点的子节点都是黑色
  5. 从任意节点到叶子节点的所有路径都包含相同数目的黑色节点

红黑树的复杂度

查找,添加,删除:(O(logn))

散列表

在HashMap中的最重要的一个数据结构就是散列表,在散列表中又使用到了红黑树和链表
散列表(Hash Table)又名哈希表/Hash表,是根据键(Key)直接访问在内存存储位置值(Value)的数据结构,他是由数组演化而来的,利用了数组支持按照下标进行随机访问数组的特性。
将键(key)映射为数组下标的函数叫做散列函数,可以表示为:hashValue=hash(key)
散列函数的基本要求:

  1. 散列函数计算得到的散列值必须是大于等于0的正整数,因为hashValue需要作为数组的下标。
  2. 如果key1==key2,那么经过hash后得到的hash值也必相同:hash(key1)==hash(key)
  3. 反之亦然

散列冲突

实际的情况想找一个散列函数能够做到对不同的key计算得到的散列值都不同几乎是不可能的,即是像著名的MD5,SHA等哈希算法也无法避免这一情况,这就是散列冲突(或者哈希冲突,哈希碰撞,就是多个key映射到同一下标)

HashMap的实现原理

HashMap的数据结构:底层使用hash标数据结构,即数组和链表或红黑树

  1. 当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标
  2. 存储时,如果出现hash值相同的key,此时有两种情况
    1. 如果key相同,则覆盖原始值
    2. 如果key不同(出现冲突),则将当前的key-value放入链表或红黑树中
  3. 获取时,直接找到hash值对应的下标,再进一步判断ey是否相同,从而找到对应值

jdk1.7与1.8的区别

  1. JDK1.8之前采用的是拉链法。拉链法:将链表和数组结合。也就是说创建了一个链表数组,数组中每一格就是一个链表。若遇到hash冲突。则将冲突的值加到链表中即可
  2. jdk1.8在解决hash冲突时有了较大的变化,当链表长度大于阈值(默认为8)时并且数组长度达到64时,将链表转化为红黑树,以减少搜索时间。扩容resize()时,红黑树拆分成的树的节点数小于等于临界值6个,则退化成链表

HashMap的put方法的具体流程

源码-常见属性

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //默认的初始容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认的加载因子
transient HashMap.Node<K,V> [] table;
transient int size;

扩容阈值==数组容量*加载因子

Map<String,String> map = new HashMap<>();
map.put("666","666");	

以上代码会发生:
在这里插入图片描述

  1. HashMap是懒惰加载,在创建对象时并没有初始化数组
  2. 在无参的构造函数中,设置了默认的加载因子是0.75

添加数据

在这里插入图片描述

HashMap的扩容机制

在这里插入图片描述

  1. 在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次扩容都是达到了扩容阈值(数组长度*0.75)
  2. 每次扩容的时候,都是扩容之前的容量的2倍
  3. 扩容之后,会创建一个数组,需要把老数组中的数据挪动到新的数组中
    1. 没有hash冲突的节点,则直接使用e.hash&(newCap-1)计算新数组的索引位置
    2. 如果是红黑树,走红黑树的添加
    3. 如果是链表,则需要遍历链表,可能需要拆分链表,判断(e.hash&oldCap),该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

HashMap的寻址算法

在这里插入图片描述
在这里插入图片描述
右移16位是扰动算法,使得hash值更加均匀,减少hash冲突
在这里插入图片描述
(n-1)&hash:得到数组中的索引,代替取模,性能更好,数组长度必须是2的n次幂

为什么HashMap的数组长度一定是2的次幂

  1. 计算索引时效率更高:如果是2的n次幂可以使用位与运算代替取模
  2. 扩容时重新计算索引效率更高:hash&oldCap==0的元素留在原来位置,否则新位置=旧位置+oldCap

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

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

相关文章

防爆巡检手持终端在燃气巡检作业中的应用

在燃气巡检作业中&#xff0c;安全始终是首要考虑的因素。面对易燃易爆的燃气环境&#xff0c;传统的巡检方式已经难以满足现代安全管理的需求。随着科技的不断进步&#xff0c;防爆巡检手持终端应运而生&#xff0c;成为燃气巡检作业的得力助手。这些终端不仅具备高度的防爆性…

docker-compose安装emqx集群(最新)(host模式)

机器&#xff1a; 10.60.0.20 10.60.0.21 10.60.0.22 一、三台机子都配置域名&#xff08;/etc/hosts&#xff09; 10.60.0.20 node1.emqx.io 10.60.0.22 node3.emqx.io 10.60.0.21 node2.emqx.io 二、docker-compose.yml&#xff08;10.60.0.21&#xff09; 其他两台机子自…

WordPress 、Typecho 站点的 MySQL/MariaDB 数据库优化

今天明月给大家分享一下 WordPress 、Typecho 站点的 MySQL/MariaDB 数据库优化&#xff0c;无论你的站点采用是 WordPress 还是 Typecho&#xff0c;都要用到 MySQL/MariaDB 数据库&#xff0c;我们以 MySQL 为主&#xff08;MariaDB 其实跟 MySQL 基本没啥大的区别&#xff0…

FHMG037、FHMG045、FHMG063比例电磁铁驱动放大器

该FHMG037、FHMG045、FHMG063比例电磁铁符合VDE0580&#xff0c;电枢空间耐压可达350 bar&#xff0c;也适用于干运行&#xff0c;磁力和在行程在横向工作范围内略有下降&#xff0c;与BEUEC比例放大器驱动工作&#xff0c;力值和电流之间很大程度上有比例关系&#xff0c;通过…

【单片机调试】mcu调试bug记录

【单片机调试】mcu调试bug记录 2023.5-2023.11待输入 2023.12-2023.22024.3-至今1.spi通信问题 2023.5-2023.11 待输入 2023.12-2023.2 辞职阶段&#xff1a;【STM32调试】寄存器调试不良问题记录持续版 2024.3-至今 1.spi通信问题 现象说明&#xff1a; mcu与afe芯片为spi通…

PDF Squeezer for Mac,让PDF压缩更高效

还在为PDF文件过大而烦恼吗&#xff1f;试试PDF Squeezer for Mac吧&#xff01;它拥有强大的压缩功能&#xff0c;可以快速将PDF文件压缩至更小的体积&#xff0c;让你的文件传输更快捷。同时&#xff0c;它还支持多种压缩方式&#xff0c;满足你的不同需求。赶快下载体验吧&a…

课题组里有一个卷王是什么体验?

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验&#xff0c;帮助大家尽早适应研究生生活&#xff0c;尽快了解科研的本质。祝一切顺利&#xff01;—…

【Linux】多线程相关第一篇:从进程谈起理解线程概念

文章目录 为什么需要线程初步认识Linux线程Linux操作系统的线程为什么要这么设计进程、线程关系梳理理解线程是CPU调度的基本单位简单认识多执行流如何划分代码 为什么需要线程 线程和进程的关系密不可分。 操作系统教材对于进程、线程的概念是这样描述的&#xff1a; 进程是…

秋招后端开发面试题 - JVM运行时数据区

目录 运行时数据区前言面试题JVM 内存区域 / 运行时数据区&#xff1f;说一下 JDK1.6、1.7、1.8 内存区域的变化&#xff1f;为什么使用元空间替代永久代作为方法区的实现&#xff1f;Java 堆的内存分区了解吗&#xff1f;运行时常量池&#xff1f;字符串常量池了解吗&#xff…

win server服务器 关闭危险端口 135,137,138,139,445的方法

通过防火墙来控制 打开控制面板 选择检查防火墙状态 选择高级设置 选择入站规则&#xff0c;再新建规则 选择端口&#xff0c;下一步 选择端口应用于啥协议&#xff0c;再指定端口&#xff0c;再下一步 选择阻止连接&#xff0c;下一步 下一步 给规则别名一下&#xff0c;方便…

STM32存储左右互搏 USB接口FATS文件读写U盘

STM32存储左右互搏 USB接口FATS文件读写U盘 STM32的USB接口可以例化为Host主机从而对U盘进行操作。SD卡/MicroSD/TF卡也可以通过读卡器转换成U盘使用。这里介绍STM32CUBEIDE开发平台HAL库实现U盘FATS文件访问的例程。 USB接口介绍 常见的USB接口电路部分相似而有不同的连接器…

Leetcode - 周赛396

目录 一&#xff0c;3136. 有效单词 二&#xff0c;3137. K 周期字符串需要的最少操作次数 三&#xff0c;3138. 同位字符串连接的最小长度 四&#xff0c;3139. 使数组中所有元素相等的最小开销 一&#xff0c;3136. 有效单词 本题就是一道阅读理解题&#xff1a; 字符串长…

Floyd+二分,蓝桥杯国赛2022[环境治理]

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 0环境治理 - 蓝桥云课 (lanqiao.cn) 二、解题报告 1、思路分析 考虑我们治理时间越长&#xff0c;灰尘度和越低&#xff0c;具有单调性 考虑 二分治理天数mid&#xff0c;1~n可以降低与其相连边 mid / n 点…

[Linux][网络][协议技术][DNS][ICMP][ping][traceroute][NAT]详细讲解

目录 1.DNS1.DNS背景2.域名简介 2.ICMP协议1.ICMP功能2.ICMP两类报文 3.ping命令4.traceroute5.NAT技术1.NAT技术背景2.NAT IP转换过程3.静态地址NAT && 动态地址NAT4.网络地址端口转换NAPT5.NAT技术的缺陷6.NAT和代理服务器 6.总结1.数据链路层2.网络层3.传输层4.应用…

APP未上架应用市场,微信商户如何快速开通APP支付

在移动互联网时代&#xff0c;APP作为企业服务用户的重要窗口&#xff0c;其支付功能的完善性直接关系到用户体验和企业的营收。然而&#xff0c;对于许多未上架应用市场的APP来说&#xff0c;如何快速开通微信APP支付功能成为了一个亟待解决的问题。本文将为您详细介绍在APP未…

AI大模型探索之路-训练篇22: ChatGLM3微调实战-从原理到应用的LoRA技术全解

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

Java | Leetcode Java题解之第79题单词搜索

题目&#xff1a; 题解&#xff1a; class Solution {public boolean exist(char[][] board, String word) {char[] words word.toCharArray();for(int i 0; i < board.length; i) {for(int j 0; j < board[0].length; j) {if (dfs(board, words, i, j, 0)) return t…

数据中心--AI时代的“炼油厂”

数据中心正在成为AI时代的“炼油厂”&#xff01; 众所周知&#xff0c;AI的高歌猛进催生了对数据的海量处理需求。为了满足蓬勃的算力需求&#xff0c;全球开启了新一轮的数据中心建设热潮&#xff0c;数据中心业务正在以指数级的速度疯狂扩张。 此番情景&#xff0c;和第二…

图书馆APP开发解决方案

uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 框架支持:springboot/Ssm/thinkphp/django/flask/express均支持 前端开发:vue.js 可选语言&#xff1a;pythonjavanode.jsphp均支持 运行软件…

摸鱼大数据——Linux搭建大数据环境——安装无界面虚拟机

前期准备工作基础环境配置 提前安装好vmware软件,准备好连接虚拟机的&#xff08;Final shell、WindTerm、CRT皆可&#xff09; 安装CentOS纯净版&#xff08;无界面版&#xff09; 1.文件 -> 创建新的虚拟机 -> 典型(推荐) -> 稍后安装操作系统 2.客户机操作系统 : …