Java集合框架笔记

1.List、Set和Map对数据处理有什么区别?

数据ListSetMap
数据结构有序,允许重复无序,不允许重复键值对,键不允许重复
存储方法数组或链表哈希表哈希表
操作方法添加、删除、修改、获取、索引访问添加、删除、判断存在添加、删除、获取、根据键查找值
应用元素排序,索引访问元素唯一性,快速查找存储键值对,快速查找值

2.Iterator 和 ListIterator 有什么区别?

特性IteratorListIterator
遍历方向单向双向
修改只能读取或删除当前迭代对象可读写
获取索引无法获取可以获取
添加元素无法添加可以添加
替换元素无法替换可以替换

问题:创建一个set集合,用一个迭代器迭代两次能得到结果吗?

答:不能,Set集合的特性是元素不能重复,如果迭代器已经遍历过所有元素,再次迭代将不会有任何新的元素可以获取,迭代器在创建后,只能遍历一次,当迭代器遍历完所有元素后,它就处于“已用完”的状态,无法再次使用。

3.遍历一个 List集合有哪些不同的方式?
(1)普通for循环
(2)增强for循环
(3)迭代器Iterator
(4)ListIterator
(5)Lamda表达式
(6)Stream流
4.ArrayList 和 Vector 的区别是什么?Stack呢?

特性ArrayListVectorStack
线程安全不是线程安全线程安全线程安全
性能
数据结构动态数组动态数组

5.HashMap是怎么解决哈希冲突的?

开放定址法也称线性探测法,就是从发生冲突的那个位置开始,按照一定次序从Hash表找到一个空闲位置然后把发生冲突的元素存入到这个位置,而在java中,ThreadLocal就用到了线性探测法来解决Hash冲突。

特性HashMapConcurrentHashMapHashtable
线程安全性不是线程安全线程安全(分段锁机制)线程安全
性能较快优于 Hashtable较慢
使用场景单线程环境多线程环境,高并发性能简单线程安全

ConcurrentHashMap的分段锁机制:

ConcurrentHashMap 将数据分成多个段 ,每个段都拥有自己的锁,类似于一个独立的 HashMap,当多个线程同时访问ConcurrentHashMap 时,它们可以同时访问不同的段,而不会互相阻塞,分段锁机制将锁的粒度从整个 HashMap 降低到每个段,从而减少了锁竞争,提高了并发性能。

6.为什么 ArrayList 的 elementData 加上 transient 修饰?

transient 关键字用于标识一个字段不应该被序列化。当一个对象被序列化时,transient 字段会被忽略,不会被写入到序列化流中。

拓展:序列化和反序列化
(1)序列化和反序列化的定义:
Java序列化就是指把Java对象转换为字节序列的过程

Java反序列化就是指把字节序列恢复为Java对象的过程。

(2)序列化最重要的作用:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。

反序列化的最重要的作用:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。

(3)序列化过程:
将对象转换为字节流的过程。
使用 ObjectOutputStream 类将对象序列化为字节流。
序列化后的字节流可以存储在磁盘上或通过网络传输。

反序列化过程:
将字节流转换为对象的过程。
使用 ObjectInputStream 类将字节流反序列化为对象。
反序列化后的对象可以被程序使用。

数据格式:
Java 序列化使用一种自定义的二进制格式来存储对象数据,避免空间浪费,序列化后的字节流包含对象的类信息、字段名和字段值。

7.多线程场景下如何使用 ArrayList?
方式一:使用Collections.synchronizedList()
ArrayList 不是线程安全的,如果遇到多线程场景,
可以通过 Collections 的 synchronizedList 方法将其转换成线程安全的容器后再使用。

方式二:使用CopyOnWriteArrayList
copyOnWriteArrayList相当于每次使用都会复制一份新的ArrayList
保证隔离,这样子线程使用就安全了,但是有个缺点,就是比较费内存,而且如果是增删改场景较多的时候,数组复制会浪费较多的时间

拓展:CopyOnWriteArrayList
CopyOnWriteArrayList 是 Java 中的一个线程安全的 ArrayList 实现,它在进行添加、删除或修改操作时,会创建一个新的数组来存储数据,并复制原数组中的所有元素。这种机制保证了在进行写操作时,不会影响其他线程的读操作。

工作原理:当进行添加、删除或修改操作时,CopyOnWriteArrayList 会创建一个新的数组,并将原数组中的所有元素复制到新数组中,CopyOnWriteArrayList 会在新的数组中进行相应的操作,将内部引用指向新的数组,从而完成写操作。

特点:
线程安全: CopyOnWriteArrayList 是线程安全的,因为在进行写操作时,它会创建一个新的数组,不会影响其他线程的读操作。
读操作快: 由于读操作不会进行任何同步操作,因此读操作的性能非常高。
写操作慢: 写操作需要创建新的数组并复制元素,因此写操作的性能较低。
内存占用高: CopyOnWriteArrayList 会占用额外的内存来存储新的数组,因此内存占用相对较高。

8.红黑树
红黑树是一种自平衡的二叉查找树,红黑树牺牲了严格的平衡性,换取了更快的插入/删除操作速度和更少的旋转操作,它是一种近似平衡的二叉树,它能够确保任何一个结点的左右子树的高度差不会超过两倍。红黑树需要满足以下五个性质:

每个结点要么是红色,要么是黑色。
根结点必须是黑色。
红色结点的子节点必须是黑色。
对于每个结点,从该结点到其所有后代叶子结点的简单路径上,均包含相同数目的黑色结点。
空结点被认为是黑色的。

9.快速失败机制 “fail-fast”
快速失败机制(Fail-Fast)是 Java 中的一种错误检测机制,它通过在迭代器遍历集合的过程中检测集合是否被修改来实现,如果在迭代过程中发现集合被修改了,迭代器会抛出 ConcurrentModificationException 异常,阻止程序继续执行。

特点:
快速检测: 快速失败机制能够快速检测到集合被修改的情况,避免潜在的错误。
异常抛出: 当检测到集合被修改时,快速失败机制会抛出 ConcurrentModificationException 异常,提醒程序员处理错误。
非线程安全: 快速失败机制本身并不保证线程安全,它只是在迭代过程中检测到集合被修改时抛出异常。

10.HashMap 的长度为什么是 2 的幂次方?
为了能让HashMap存取高效,尽量减少碰撞,需要将散列表的数据分配均匀。
补充:使用HashMap查询或插入数据时,需要先对数组长度取模运算,index = hash%length,得到余数用来存放位置,也就是对应的数组角标。取余操作中,如果除数是2的幂次,则等价于除数减一的与操作,即hash%length=hash&(length-1),这里采用&运算比%运算效率高,故HashMap的长度需是2的幂次方。

11.HashMap为什么不直接使用hashCode()处理后的哈希值直接作为table的下标?
(1)hashCode() 方法返回的是一个 int 类型的值,其范围是 2-31 到 231-1,如果直接使用 hashCode() 作为 table 的下标,则需要一个容量为 231 的 table,这会占用巨大的内存空间不利于提升性能。
(2)如果直接使用 hashCode() 作为 table 的下标,会出现具有相同 hashCode() 值的 key 会被映射到同一个位置,出现哈希冲突,导致数据存储和查找效率低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值