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

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

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

相关文章

webpack5以下的项目,前端引入node的path模块需要额外配置

webpack5以下的项目&#xff0c;前端import * as path from path时需要额外配置&#xff0c;这里以vue.config.js为例 刚开始引入时报错 其实就是在打包前端项目的时候&#xff0c;将path模块替换成 path-browserify 模块&#xff0c;所以还需要安装 path-browserfify 模块 …

【Linux】磁盘文件

思维导图 学习目标 了解磁盘的物理结构和存储结构&#xff0c;并将其存储结构进行抽象&#xff01;&#xff01; 一、了解一下磁盘及其物理结构 1.1 计算机只认识二进制 什么是二进制&#xff1f;&#xff1f;0&#xff0c;1是被规定出来的&#xff0c;在计算机里面我们用高低…

Excel Module: Iteration #1 EasyExcel生成下拉列表模版时传入动态参数查询下拉数据

系列文章 EasyExcel生成带下拉列表或多级级联列表的Excel模版自定义校验导入数据(修订) 目录 系列文章前言仓库一、实现1.1 下拉元数据对象1.2 构建下拉元数据的映射关系1.3 框架方式1.3.1 框架实现1.3.2 框架用例模版类加载下拉业务导出接口 1.4 EasyExcel方式1.4.1 EasyExce…

灵活QinQ

拓扑图 配置 sysname AR1 # interface GigabitEthernet0/0/0.10dot1q termination vid 10ip address 12.1.1.1 255.255.255.0 arp broadcast enable # interface GigabitEthernet0/0/0.20dot1q termination vid 20ip address 21.1.1.1 255.255.255.0 arp broadcast enable # …

重学SpringBoot3-SPI机制

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-SPI机制 什么是 SPI&#xff1f;Spring Boot 中的 SPI 机制spring.factories 文件自动配置的实现启动流程中的作用 SPI实际应用步骤 1: 新建模块步骤 2:…

(超详细讲解)实现将idea的java程序打包成exe (新版,可以在没有java的电脑下运行,即可以发给好朋友一起玩)

目录 实现打包到exe大概步骤 工具准备 1.将java程序文件打包成jar文件 2.准备好jre文件 3.使用exe4j软件打包好 4.最终打包 实现打包到exe大概步骤 1.打包需要满足的条件&#xff1a;将java文件转成jar文件的工具exe4j、 以及需要满足jdk1.8以上&#xff08;因安装exe4…

Embedding技术学习

可能很多人并没有关注Embedding技术&#xff0c;但实际上它是GPT非常重要的基础&#xff0c;准备的说&#xff0c;它是GPT模型中理解语言/语义的基础。 【解释什么是Embedding】 对于客观世界&#xff0c;人类通过各种文化产品来表达&#xff0c;比如&#xff1a;语言&#x…

如何快速提取出一个文件里面全部指定类型的文件的全部路径

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 打开工具&#xff0c;切换到第五个模块&#xff0c;文件批量复制模块&#xff08;快捷键&#xff1a;Ctrl5&#xff09; 点击右边的“搜索添加”按钮&#…

unordered系列关联式容器底层哈希结构的介绍,哈希表的模拟实现(哈希冲突的解决方法采用闭散列线性探测)

目录 前言 unordered系列关联式容器之所以处理数据的效率比较高&#xff0c;是因为底层使用了哈希结构&#xff0c;哈希结构的优点是&#xff1a;不经过任何比较&#xff0c;一次直接从表中得到要搜索的元素&#xff0c;通过某种函数(hashFunc)使元素的存储位置与它的关键码之…

mapreduce | 自定义Partition分区(案例2)

1.需求 统计每个手机号消费总金额&#xff0c;按照消费金额降序排序&#xff0c;最终联通、电信、移动分别写入不同的文件。 130、131、132&#xff08;联通&#xff09; 133&#xff08;电信&#xff09; 135、136、137、138、139 &#xff08;移动&#xff09; 手机号,消费记…

全局变量在函数中的使用:Python 编程技巧解析

在Python编程中&#xff0c;全局变量是一种在程序的多个部分中共享数据的机制。全局变量在函数中使用时&#xff0c;需要特别注意其作用域和访问方式。本文将详细讲解如何在函数中使用全局变量&#xff0c;并提供示例代码&#xff0c;帮助初学者深入理解这一概念。 基本原理 …

AI作画涉及的深度学习算法

AI作画中使用的深度学习算法多种多样&#xff0c;这些算法主要基于神经网络的结构和训练方式&#xff0c;以生成和改进艺术作品。以下是一些在AI作画中常用的深度学习算法&#xff1a; 生成对抗网络&#xff08;GANs, Generative Adversarial Networks&#xff09;&#xff1a…

Linux —— 线程

Linux —— 线程 什么是线程Linux如何实现线程Winodws如何实现线程使用一下线程pthread_create函数原型参数说明返回值 如何解决 ps -aL 查看线程线程为什么轻量 我们今天进入线程的学习&#xff1a; 什么是线程 我们先来了解一个笼统的概念&#xff1a;简单来说&#xff0c;…

计算机发展史故事【12】

芯片计算机 众所周知&#xff0c;所谓286、386、486 个人电脑等名称的起源&#xff0c;在于它们采用了英特尔公司研制的微处理器X86 系列芯片286、386 和486。然而&#xff0c;这种以数字为电脑命名的奇特现象&#xff0c;却来源于霍夫博士等人发明的世界上第一个微处理器芯片…

动态路由-链路状态路由协议ospf案例

实验拓扑和要求如图 ospf实验 1.设置各个接口地址 2.测试ar5到ar6的连通性 3.配置ospf协议&#xff0c;routerid&#xff0c;area&#xff0c; 详细的网络信息&#xff0c;等待网络收敛后&#xff0c; 查看ospf信息&#xff0c;路由表信息&#xff0c;再次测试连通性 注意区域…

防火墙技术基础篇:网络地址转换(NAT):防火墙技术的核心机制

防火墙技术基础篇&#xff1a;网络地址转换&#xff08;NAT&#xff09;&#xff1a;防火墙技术的核心机制 网络地址转换&#xff08;NAT&#xff09;是现代网络架构中不可或缺的一个组成部分&#xff0c;尤其在防火墙技术的实现中扮演着重要角色。本文旨在全面解读NAT的工作机…

AI算法-高数5.1-线性代数-向量定义、表示和向量间的关系

看线性代数这篇文章&#xff08;AI算法-高数5-线性代数1-基本概念、向量-CSDN博客&#xff09;理解有些吃力的朋友们&#xff0c;可以先学下宋浩老师的这些课程。 宋浩老师&#xff1a; 3.1 n维向量及其运算_哔哩哔哩_bilibili 3.2 向量间的线性关系&#xff08;一&#xff…

MFC编程之设计美丽的对话框

目录 写在前面&#xff1a; Part 1&#xff1a;美美的设计一下计算器的布局 1.描述文字&#xff1a; ​编辑 2.ID&#xff1a; Part 2&#xff1a;美美熟悉一下计算器的工作流程 Part 3&#xff1a;美美设计一下控件功能 1.edit control&#xff1a; 2.相关变量初始化&…

Agilent MSO9404A、Keysight MSO9404A示波器,4 GHz,4 通道,20 GSa/s

Agilent MSO9404A、Keysight MSO9404A、HP MSO9404A 示波器&#xff0c;4 GHz&#xff0c;4 通道&#xff0c;20 GSa/s Keysight MSO9404A 示波器配备 15 英寸 XGA 显示屏&#xff0c;封装深度仅为 9 英寸&#xff08;23 厘米&#xff09;&#xff0c;重量仅为 26 磅&#xff…

AI地名故事:笔岗村

笔岗村&#xff0c;实际上是由笔村和宏岗村两个古老的村落合并而成的。南宋度宗元年&#xff0c;也就是公元1265年&#xff0c;笔村开始建立。随着时间的推移&#xff0c;到了宋代后期&#xff0c;宏岗村也相继建立。这两个村落各自承载着丰富的历史和文化&#xff0c;最终在历…