集合 Collection

简介: Java集合框架包含List、Set和Map三大接口。List如ArrayList和LinkedList,支持有序可重复元素;Set如HashSet和TreeSet,保证元素唯一性;Map如HashMap和TreeMap,以键值对存储数据。ArrayList基于动态数组,查询快而增删慢;LinkedList基于链表,适合频繁插入删除。HashMap底层为数组+链表/红黑树,利用哈希优化存取效率;ConcurrentHashMap通过分段锁实现线程安全。LinkedHashSet保持插入顺序,TreeSet支持排序。选择合适集合可提升程序性能与可维护性。

集合 Collection

List有序可重复 Set无序不重复 Map为key-value

List

ArrayList

底层数据结构

基于动态数组实现支持随机访问

自动扩容

每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容以满足添加数据的需求,每次进行扩容时会将老数组中的元素重新拷贝一份到新的数组中。每次数组容量的增长大约为其容量的1.5倍,这种代价是很高的,因此我们在实际使用时应尽量避免数组容量的扩张。

Fail-Fast机制:

ArrayList采用了快速失败的机制,通过记录modCount参数来实现。

说说什么是Fail-Fast机制:

Fail-Fast 机制是 Java 集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生 fail-fast 事件。
例如:当某一个线程 A 通过 iterator 去遍历某集合的过程中,若该集合的内容被其他线程所改变了,那么线程 A 访问集合时,就会抛ConcurrentModificationException 异常,产生 fail-fast 事件。这里的操作主要是指 add、remove 和 clear,对集合元素个数进行修改。
解决办法:建议使用“java.util.concurrent 包下的类”去取代“java.util 包下的类”。
可以这么理解:在遍历之前,把 modCount 记下来 expectModCount,后面 expectModCount 去和 modCount 进行比较,如果不相等了,证明已并发了,被修改了,于是抛出 ConcurrentModificationException 异常。

Vector

和ArrayList类似但它是线程安全的

LinkedList

基于双向链表实现只能顺序访问但可以在列表中快速的插入和删除元素

底层数据结构

LinkedList底层通过双向链表实现

说说ArrayList和LinkedList的区别:

ArrayList

  • 优点:实现了基于动态数组的数据结构。存储地址物理连续,查询效率比较高,随机读取速率比较高。
  • 缺点:因为地址连续,要移动数据的时候比如插入删除的操作效率就会比较低。

LinkedList

  • 优点:基于链表的数据结构存储地址逻辑上是连续的,但物理上并不是连续,所以开辟内存空间时不需要一个连续的内存地址。新增和删除操作效率比较高。LinkedList比较适用于头尾操作需要插入指定位置的场景。
  • 缺点:因为LinkedList需要移动指针,查询效率比较低。

Stack & Queue

Queue 队列

Deque 双向队列

PriorityQueue 优先队列

Map

TreeMap

基于红黑树实现

HashMap

基于哈希表实现

底层数据结构

jdk1.7 底层: 数组+链表

jdk1.8 底层: 数组+链表+红黑树

初始为一个默认大小为16的数组,put操作的时候hash运算之后取模(位运算,直接面向二进制位),存一个Object对象,存储为单链表,当单链表中的对象过多的时候(链表长度8个,数组长度64个),时间复杂度为O(N),查询较慢,将链表升级为红黑树,时间复杂度为O(log N)

红黑树的特征:

每个节点是黑色或者红色

根节点是黑色

每个叶子节点都是黑色

如果一个叶子节点是红色,那么其子节点必须都是黑色的

从一个节点到该节点的子孙节点上所有路径包含相同数目的黑节点

扩容

数组长度<64,链表长度>8

通过扩容将数组重新分配,从而提高查询性能

jdk1.7 :rehash

jdk1.8 :hash & 老数组长度

低位:保留原位

高位:原下标+扩容大小

HashMap的长度为什么是2的N次方呢?

为了能使HashMap存取数据的效率尽可能高,尽可能减少哈希值的碰撞,也就是说尽量将数据均匀分配,每个链表或者红黑树的长度尽量相等。

我们可能首先会取到想到%取模操作来实现。

取余操作中如果除数是2的幂次,则等价于与其除数减一的与(&)操作(也就是说hash % length == hash &(length - 1) 的前提是 length是2的n次方)。采用二进制位操作&相对于取余能够提高运算效率。

ConcurrentHashMap

ConcurrentHashMap支持线程安全并且效率更高,因为ConcurrentHashMap引入了分段锁。

ConcurrentHashMap 在 JDK 1.8 之前是采用分段锁来现实的 Segment + HashEntry,
Segment 数组大小默认是 16,2 的 n 次方;

JDK 1.8 之后,采用 Node + CAS + Synchronized
来保证并发安全进行实现。

LinkedHashMap

使用双向链表来维护元素的顺序顺序为插入的顺序或者最近最少使用(LRU)顺序

经典用法

可以轻松实现一个采取FIFO替换策略的缓存,具体说来,LinkedHashMap有一个子类方法protected boolean removeEldestEntry(Map.Entry<K,V> eldest),该方法的作用是告诉Map是否要删除“最老”的Entry,所谓最老就是当前Map中最早插入的Entry,如果该方法返回true,最老的那个元素就会被删除。在每次插入新元素之后LinkedHashMap会自动询问removeEldestEntry()是否要删除最老的元素。这样只需要在子类中重载该方法,当元素个数超过一定数量时让removeEldestEntry()返回true,就能够实现一个固定大小的FIFO策略的缓存。

底层数据结构

在HashMap的基础上,使用双向链表的形式将所有的NT连接起来为了保证元素的迭代顺序和插入的顺序相同

Set

TreeSet

基于红黑树实现,支持有序性操作但查找效率不如HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 由于呃link list需要移动指针所以查询的效率比较低则为 O(logN)。

HashSet

基于哈希表实现,支持快速查找,但不支持有序性操作。并且会导致元素插入顺序失序,也就是说遍历HashSet得到的结果是不确定的。

LinkedHashSet

具有HashSet的查找效率且内部使用双向链表来维护元素的插入顺序。

说说List,Set,Map三者的区别?
List: List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象
Set: 不允许重复的集合。不会有多个元素引用相同的对象。
Map: 使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。

相关文章
|
2月前
|
存储 缓存 算法
JVM
本课程深入讲解JVM虚拟机核心知识,涵盖类加载机制、运行时数据区、对象生命周期、垃圾回收算法及调优实战等内容,帮助开发者夯实Java底层原理,提升系统性能与故障排查能力,助力面试与实际项目应用。
106 0
|
3月前
|
存储 Java 测试技术
Java基础 - 面向对象
面向对象编程是Java的核心,包含封装、继承、多态三大特性。封装隐藏实现细节,提升代码可维护性与安全性;继承实现类间IS-A关系,支持代码复用;多态通过继承、重写与向上转型,实现运行时方法动态绑定,提升系统扩展性与灵活性。
|
3月前
|
存储 缓存 安全
Java基础 - 知识点
Java基础知识点涵盖语言特性、面向对象与基本数据类型、缓存池机制、String类特性、参数传递、类型转换、继承、抽象类与接口区别、重写与重载、Object通用方法及关键字使用等核心内容,是掌握Java编程的重要基石。
|
canal 关系型数据库 MySQL
es添加索引命令行和浏览器添加索引--图文详解
es添加索引命令行和浏览器添加索引--图文详解
408 1
|
1月前
|
人工智能 Java API
构建基于Java的AI智能体:使用LangChain4j与Spring AI实现RAG应用
当大模型需要处理私有、实时的数据时,检索增强生成(RAG)技术成为了核心解决方案。本文深入探讨如何在Java生态中构建具备RAG能力的AI智能体。我们将介绍新兴的Spring AI项目与成熟的LangChain4j框架,详细演示如何从零开始构建一个能够查询私有知识库的智能问答系统。内容涵盖文档加载与分块、向量数据库集成、语义检索以及与大模型的最终合成,并提供完整的代码实现,为Java开发者开启构建复杂AI智能体的大门。
928 58
|
2月前
|
安全 Java C语言
JUC
简介:本文详解Java并发编程核心机制,涵盖CAS原理及其在AtomicInteger等类中的应用,探讨ABA问题、自旋开销及多变量原子操作限制,并介绍Unsafe类与AQS同步框架,帮助开发者深入理解无锁与阻塞同步实现原理。
114 0
|
2月前
|
存储 缓存 安全
Java 并发
本节介绍了Java并发编程的核心问题及解决机制。由于CPU、内存和I/O速度差异,多线程环境下会出现可见性、原子性和有序性三大问题。Java通过JMM(Java内存模型)提供volatile、synchronized等关键字及Happens-Before规则,保障线程安全。
|
4月前
|
计算机视觉 流计算 Python
人脸识别照片眨眼张嘴生成器,一键生成眨眼照片app,怎么用一张照片做人脸识别
基于Python的人脸识别照片动画生成系统,支持眨眼和张嘴动作。使用OpenCV、dlib等技术实现,可输出GIF或序列帧。代码包含完整的人脸检测
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
255 2