Java后端开发面试题——集合篇

ArrayList底层的实现原理是什么

底层数据结构

ArrayList底层是用动态的数组实现的

初始容量

ArrayList初始容量为0,当第一次添加数据的时候才会初始化容量为10

扩容逻辑

ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组

添加逻辑

确保数组已使用长度(size)加1之后足够存下下一个数据.

​计算数组的容量,如果当前数组已使用长度+1后的大于当前的数组长度,则调用grow方法扩容(原来的1.5倍)

确保新增的数据有地方存储之后,则将新元素添加到位于size的位置上。​

返回添加成功布尔值。

ArrayList list=new ArrayList(10)中的list扩容几次

该语句只是声明和实例了一个 ArrayList,指定了容量为 10,未扩容

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

数组转List

java 复制代码
String[] strs = {"aaa","bbb","ccc"};
List<String> list = Arrays.asList(strs);

List转数组

java 复制代码
    List<String> list = new ArrayList<String>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    String[] array = list.toArray(new String[list.size()]);

用Arrays.asList转List后,如果修改了数组内容,list受影响吗

修改了数组的内容,list会受影响,因为它的底层使用的Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装而已,最终指向的都是同一个内存地址

List用toArray转数组后,如果修改了List内容,数组受影响吗

修改了list内容,数组不会影响,当调用了toArray以后,在底层是它是进行了数组的拷贝,跟原来的元素就没啥关系了,所以即使list修改了以后,数组也不受影响

ArrayList 和 LinkedList 的区别是什么?

底层数据结构

ArrayList 是动态数组的数据结构实现

LinkedList 是双向链表的数据结构实现

操作数据效率

查找时间复杂度都是O(n)

新增和删除时间复杂度是O(n)

内存空间占用

ArrayList底层是数组,内存连续,节省内存

LinkedList 是双向链表需要存储数据,和两个指针,更占用内存

线程安全

都不是线程安全的

在方法内使用,局部变量则是线程安全的

使用线程安全的ArrayList和LinkedList

java 复制代码
List<Object> syncArrayList = Collections.synchronizedList(new ArrayList<>());
List<Object> syncLinkedList = Collections.synchronizedList(new LinkedList<>());

二叉搜索树

在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值,而右子树节点的值都大于这个节点的值,没有键值相等的节点

红黑树

一种自平衡的二叉搜索树(BST)

性质1:节点要么是红色,要么是黑色

性质2:根节点是黑色

性质3:叶子节点都是黑色的空节点

性质4:红黑树中红色节点的子节点都是黑色

性质5:从任一节点到叶子节点的所有路径都包含相同数目的黑色节点

在添加或删除节点的时候,如果不符合这些性质会发生旋转,以达到所有的性质

散列表(Hash Table)

是根据键(Key)直接访问在内存存储位置值(Value)的数据结构,利用了数组支持按照下标进行随机访问数据的特性

散列函数计算得到的散列值必须是大于等于0的正整数,因为hashValue需要作为数组的下标。

如果key1==key2,那么经过hash后得到的哈希值也必相同即:hash(key1) == hash(key2)

如果key1 != key2,那么经过hash后得到的哈希值也必不相同即:hash(key1) != hash(key2)

散列冲突

不同的key计算得到的散列值都不同几乎是不可能的

链表法(拉链)

所有散列值相同的元素我们都放到相同槽位对应的链表中,链表法中的链表如果是红黑树(可以防止DDos攻击)

HashMap实现原理

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

当我们往HashMap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标

存储时,如果出现hash值相同的key,此时有两种情况

a. 如果key相同,则覆盖原始值;

b. 如果key不同(出现冲突),则将当前的key-value放入链表或红黑树中

获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

链表的长度大于8 且 数组长度大于64 转换为红黑树(减少搜索时间)

红黑树拆分成的树的结点数小于等于临界值6个,则退化成链表

jdk1.7采用的是拉链法 链表和数组相结合

HashMap的put方法的具体流程

HashMap是懒惰加载,在创建对象时并没有初始化数组

在无参的构造函数中,设置了默认的加载因子是0.75

讲一讲HashMap的扩容机制

hashMap的寻址算法

计算对象的 hashCode()

再进行调用 hash() 方法进行二次哈希, hashcode值右移16位再异或运算,让哈希分布更为均匀

最后 (capacity -- 1) & hash 得到索引

hashmap在1.7情况下的多线程死循环问题

++尾插法++

相关推荐
鲤籽鲲4 分钟前
C# Random 随机数 全面解析
android·java·c#
zquwei23 分钟前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
TT哇29 分钟前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
火烧屁屁啦1 小时前
【JavaEE进阶】初始Spring Web MVC
java·spring·java-ee
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
w_31234541 小时前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
岁岁岁平安1 小时前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA1 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
Q_19284999061 小时前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
张国荣家的弟弟2 小时前
【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
java·jar·bi