首页 > 编程语言 >java集合知识整理1:Java集合概览

java集合知识整理1:Java集合概览

时间:2024-09-23 16:51:24浏览次数:3  
标签:Set java 实现 List 接口 并发 线程 集合 Java

目录


Java集合概览

java集合也叫做容器,主要由两大接口派生而来:一个是Collection接口,主要用于存放单一元素,另一个是Map接口,主要存放键值对。对于Collection接口,下面又有三个主要的子接口:List、Set、Queue。
在这里插入图片描述

List,Set,Queue,Map四者的区别?

  • List: 存储的元素是有序的,可重复的。
  • Set: 存储的元素不可重复,无序。
  • Queue: 有序,可重复,先进先出。
  • Map: 使用键值对(key-value)存储,key是无序的、不可重复的,value是无需的、可重复的,每个键最多映射到一个值。

注意:有序、无序指的是是否按存放顺序存储。


List 接口

List 接口表示有序的集合,允许重复的元素,并可以通过索引访问元素。

主要实现类:

  1. ArrayList:基于动态数组的实现,适合随机访问。
  2. LinkedList:基于双向链表的实现,适合频繁的插入和删除操作。
  3. Vector:实现了与 ArrayList 类似,但它是同步的,适合多线程环境。
  4. Stack:继承自 Vector,实现了后进先出的栈数据结构。

ArrayList 和 LinkedList,默认情况下不是线程安全的。如果你需要一个线程安全且高效的 List 实现,有几种选择:

  1. 使用 Collections.synchronizedList
    这是最简单的方法,通过包装现有的 List 实现类来提供同步支持。
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());

这个方法为所有的访问方法添加了同步锁,这是线程安全的,但在高并发环境下性能可能不是最优的,因为每次访问都需要获取锁。

  1. 使用 CopyOnWriteArrayList
    CopyOnWriteArrayList 是 java.util.concurrent 包提供的线程安全的 List 实现,非常适合读多写少的场景。
List<String> copyOnWriteArrayList = new CopyOnWriteArrayList<>();

CopyOnWriteArrayList 的特点是:

读操作不加锁:读操作不会阻塞,因为是操作的快照副本。
写操作代价高:每次写操作(添加、修改、删除)会创建整个列表的一个新副本,适合读多写少的场景。

  1. 使用 ConcurrentLinkedQueue
    虽然 ConcurrentLinkedQueue 不是 List 实现,但它提供了一个高效的、线程安全的队列,如果你需要先进先出的语义,可以考虑这个选项。
Queue<String> concurrentLinkedQueue = new ConcurrentLinkedQueue<>();
  1. 使用 Vector
    Vector 是线程安全的 List 实现类,每个方法都进行了同步处理,但它相对较老且性能一般,通常不推荐在新项目中使用。
List<String> vector = new Vector<>();

总结
高并发读多写少:选择 CopyOnWriteArrayList。
简单同步:使用 Collections.synchronizedList 包装 ArrayList 或 LinkedList。
FIFO 队列:考虑 ConcurrentLinkedQueue 作为替代。
传统方法:Vector 是线程安全的,但性能较低,建议仅用于维护旧代码。
根据你的具体需求和场景选择适合的 List 实现,可以确保在多线程环境下既满足线程安全要求,又能提供良好的性能。


set接口

Set 接口表示无序的集合,不允许重复元素。

主要实现类:

HashSet:基于哈希表的实现,提供快速的查找和插入操作。
LinkedHashSet:继承自 HashSet 并保留插入顺序。
TreeSet:基于红黑树的实现,元素自动排序。

Set 实现(如 HashSet、TreeSet、LinkedHashSet)都不是线程安全的。如果你需要一个线程安全且高效的 Set 实现,可以考虑以下选项:

  1. 使用 Collections.synchronizedSet
    这是最简单的方法,通过包装现有的 Set 实现类来提供同步支持。
Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());

这个方法为所有的访问方法添加了同步锁,虽然是线程安全的,但在高并发环境下性能可能不是最优的,因为每次访问都需要获取锁。

  1. 使用 ConcurrentSkipListSet
    ConcurrentSkipListSet 是 java.util.concurrent 包提供的线程安全的 Set 实现,基于 ConcurrentSkipListMap。
Set<String> concurrentSkipListSet = new ConcurrentSkipListSet<>();

ConcurrentSkipListSet 的特点是:

线程安全:通过细粒度的锁和无锁操作实现高效并发。
自然排序:基于跳跃表,元素按自然顺序排序(或者按提供的比较器排序)。

它是一种基于层级结构的链表,元素按顺序存储,同时具有多层链表辅助实现快速访问。

  1. 跳跃表的基本原理
  • 层级结构:跳跃表由多个层构成。底层(Level 0)是一个单链表,包含所有元素。每一层向上,元素数量减少,形成一个塔形结构。每层的节点指向下层链表的一些节点。
  • 快速访问:通过多层索引,跳跃表实现了从高层跳跃到低层的功能,大幅加快了插入、删除和查找操作的速度。
  • 概率性平衡:跳跃表自动平衡自己,通过随机机制决定每个元素所在的层,通常每层的数量是下面一层的一半。
  1. 使用 CopyOnWriteArraySet
    CopyOnWriteArraySet 是实现了 Set 接口的线程安全集合类,内部是基于 CopyOnWriteArrayList 实现的。特别适合读操作远多于写操作的场景。
Set<String> copyOnWriteArraySet = new CopyOnWriteArraySet<>();

CopyOnWriteArraySet 的特点是:

读操作不加锁:读操作不会阻塞,因为是操作的快照副本。
写操作代价高:每次写操作(添加、删除)都会创建整个集合的一个新副本,适合读多写少的场景。
4. 使用 ConcurrentHashMap 的 KeySet
自 Java 8 以来,ConcurrentHashMap 提供了一种高效的并发 Set 实现,通过 ConcurrentHashMap.keySet(defaultValue)

Set<String> concurrentHashSet = ConcurrentHashMap.newKeySet();

这是一个高效的线程安全 Set,并且继承了 ConcurrentHashMap 的并发性能优势。

总结
简单同步:使用 Collections.synchronizedSet 包装 HashSet 或其他 Set 实现。
高并发读多写少:选择 CopyOnWriteArraySet。
自然排序、高并发:选择 ConcurrentSkipListSet。
高并发且无序:选择基于 ConcurrentHashMap 的 newKeySet() 方法。
通过以上几个实现,你可以根据并发需求和性能考虑选择最合适的线程安全 Set 实现。


Queue接口

Queue 接口表示一个先进先出的队列,用于按顺序处理元素

主要实现类:

  1. LinkedList:既实现了 List 接口,也实现了 Queue 接口,适合实现双端队列。
  2. PriorityQueue:基于堆排序的实现,元素按自然顺序或指定的比较器排序。
  3. ArrayDeque:实现了双端队列(Deque)接口,提供了比 LinkedList 更高效的队列操作。

如果你需要一个线程安全且高效的 Queue 实现,Java 的并发包 java.util.concurrent 提供了一些强大的工具。选择合适的实现取决于具体的使用场景,例如是否需要阻塞队列,是否对元素的有序性有要求等。

线程安全的 Queue 实现

  1. ConcurrentLinkedQueue
    ConcurrentLinkedQueue 是一个基于无锁算法的高效非阻塞队列实现,适用于高并发环境中的生产者-消费者场景。

  2. BlockingQueue 家族

  • ArrayBlockingQueue
    ArrayBlockingQueue 是一个基于数组的阻塞队列,固定容量。队列满时插入操作将阻塞,队列空时移除操作将阻塞。

  • LinkedBlockingQueue
    LinkedBlockingQueue 是一个基于链表的阻塞队列,可指定容量限制。如果未指定容量,默认大小是 Integer.MAX_VALUE。

  • PriorityBlockingQueue
    PriorityBlockingQueue 是一个带优先级的阻塞队列,使用自然排序或提供的比较器对元素进行排序。

  • DelayQueue
    DelayQueue 是一个延迟队列,队列中的元素只能在指定的延迟时间之后才能被消费。通常用于定时任务调度。

  • SynchronousQueue
    SynchronousQueue 是一个不存储元素的队列,每一个 put 操作必须等待一个 take 操作,反之亦然。

  1. TransferQueue
  • LinkedTransferQueue
    LinkedTransferQueue 是 TransferQueue 接口的实现,支持元素的传递。如果消费者已经等待,生产者可以将元素直接传递给消费者。

总结
根据不同使用场景和需求,你可以选择合适的线程安全且高效的 Queue 实现:
高并发、非阻塞队列:使用 ConcurrentLinkedQueue。
需要阻塞行为:使用 BlockingQueue 相关实现,如 ArrayBlockingQueue、LinkedBlockingQueue。
需要优先级:使用 PriorityBlockingQueue。
需要延迟队列:使用 DelayQueue。
点对点通信:使用 SynchronousQueue。
自由传递(生产者可直接传递给消费者):使用 LinkedTransferQueue。
通过这些高级队列实现,Java 提供了丰富的工具来处理各种多线程场景,确保高效和线程安全。

Map 接口

Map 接口表示键值对的集合,键唯一,值可以重复。

主要实现类:

  1. HashMap:基于哈希表的实现,提供快速的查找和插入操作。
  2. LinkedHashMap:继承自 HashMap 并保留插入顺序。
  3. TreeMap:基于红黑树的实现,键自动排序。
  4. Hashtable:与 HashMap 类似,但它是同步的,适合多线程环境。
  5. ConcurrentHashMap:设计用于并发场景,提供了高效的并发操作支持。

Map 接口的默认实现类(如 HashMap, TreeMap 等)并不是线程安全的。所以在多线程环境中使用的时候,需要考虑线程安全且高效的实现。Java 提供了一些线程安全的 Map 实现,主要在 java.util.concurrent 包中。

  1. ConcurrentHashMap
    ConcurrentHashMap 是最常用的线程安全高效 Map 实现。它通过细粒度的锁机制(如分段锁和CAS操作)实现了高效的并发访问,适用于大多数并发场景。

特点:

高效并发:允许并发读取,写操作使用锁分片,减少锁争用。
无锁读取:大多数读取操作是无锁的,通过CAS原子操作更新值,使读写分离。
默认大小:默认初始容量为 16,扩容时通过双倍扩容机制。

  1. Collections.synchronizedMap
    Collections.synchronizedMap 提供了一种将现有 Map 转换为线程安全实现的简单方法。它对所有方法进行了同步包装,即每个访问方法都通过对相应同步块加锁来实现线程安全。

特点:

简单易用:能快速将任何 Map 实现转换为线程安全的实现。
全局锁:使用的是单独的全局锁,在高并发情况下性能不佳。

  1. ConcurrentSkipListMap
    ConcurrentSkipListMap 是一个基于跳跃表(Skip List)数据结构的线程安全 Map 实现,元素按照键的自然顺序或指定的比较器顺序存储。

特点:

有序性:提供键的自然排序或指定的排序器排序,适合需要顺序访问的场景。
高效并发:支持高效的并发读写操作,使用无锁操作和细粒度锁。
适合应用:适用于需要顺序访问和高并发操作的应用,如缓存、限流控制等

总结
根据不同的使用场景和需求,你可以选择以下线程安全且高效的 Map 实现:

  • 高并发和无序存储:选择 ConcurrentHashMap。
  • 快速转换现有 Map:使用 Collections.synchronizedMap 包装现有 Map 实现。
  • 高并发和有序存储:选择 ConcurrentSkipListMap,适用于需要顺序操作的场景。
    通过理解和应用这些并发 Map 实现,你可以在多线程环境中高效、安全地使用映射集合,确保数据一致性和操作效率。

其他相关接口和类

除了上述接口和实现类,Java 集合框架还包括一些其他常用的接口和辅助类:

  1. Deque 接口:表示双端队列,既可以从两端插入和移除元素。
    实现类:ArrayDeque 和 LinkedList
  2. SortedSet 接口:继承自 Set 接口,表示有序的集合。
    实现类:TreeSet
  3. NavigableSet 接口:继承自 SortedSet 接口,提供了导航方法。
    实现类:TreeSet
  4. SortedMap 接口:继承自 Map 接口,表示有序的键值对集合。
    实现类:TreeMap
  5. NavigableMap 接口:继承自 SortedMap 接口,提供了导航方法。
    实现类:TreeMap

没有了,感谢大家阅读,这篇就是分类一下,可以让人好记忆,系统的认识一下Java集合。以后我会持续更新每个集合框架更深入的理解。

标签:Set,java,实现,List,接口,并发,线程,集合,Java
From: https://blog.csdn.net/LSP20020926/article/details/142454595

相关文章

  • JavaWeb -Servlet对表单数据的处理 例:登录系统
    一、创建html文件并添加框架内容<tr></tr>是表格标签<td></td>是单元格标签1.添加用户名和密码<inputtype="text"name="username">文本格式(text),函数名是username。<inputtype="password"name="password">密码格式(password),函数名......
  • JavaSE---Fail-Fast
    总结主要用于集合类中,以确保在遍历集合时如果集合本身被修改,则会立即抛出ConcurrentModificationException异常。原理内部计数器:每个集合对象都有一个内部计数器,称为modCount(modificationcount)。每当集合结构被修改(比如添加或删除元素),这个计数器就会增加。迭代器检查:当......
  • 数据结构与算法——Java实现 12.习题——合并有序链表
    目录21.合并两个有序链表方法1递归思路方法2迭代思路 完整代码结点类方法 人各有所感,角度不同又怎能感同身受                                                ——24.9.2321.合并两个有序链表将两个......
  • 静态轮播图java
    静态轮播图是一种常见的网页设计元素,它可以通过一系列的静态图片来展示内容。在Java中,你可以使用JavaFX或Swing来创建静态轮播图。下面,我将提供一个简单的JavaSwing示例,来演示如何创建一个基本的静态轮播图。准备工作首先,确保你已经安装了Java开发环境(例如,JDK)和JavaSwing库。如果......
  • Java 线程机制
    目录1进程和线程2串行、并行和并发3Java实现多线程的三种方法3.1继承 Thread 类3.2 实现 Runnable 接口3.3 实现 Callable 接口4线程常用API4.1设置优先级4.2线程休眠4.3线程让步4.4线程重点(加入)4.5线程中断4.6线程守护4.7获取线程ID4.8获......
  • java+vue计算机毕设儿童教育系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在信息化高速发展的今天,教育领域正经历着前所未有的变革。随着社会对儿童教育质量要求的不断提升,传统教育模式已难以满足个性化、高效化、互动化的学......
  • java+vue计算机毕设短视频的推荐平台【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展和智能设备的普及,短视频已成为人们日常生活中不可或缺的一部分,其碎片化、高传播性及强娱乐性的特点深受各年龄段用户的喜爱......
  • java+vue计算机毕设多吃点订餐系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着移动互联网技术的飞速发展,人们的日常生活方式正经历着前所未有的变革,特别是在餐饮消费领域。快节奏的生活使得“外卖经济”迅速崛起,成为现代人解......
  • 2024最新版Java面试题及答案汇总
    1.对字符串的都有哪些方法?详细说明下。具体有String、StringBuffer和StringBuilder这三个类。String是不可变类,每次操作都会生成新的String对象,并将结果指针指向新的对象,由此会产生内存碎片。如果要频繁对字符串修改,建议采用StringBuffer和StringBuilder。StringBuff......
  • 最新整理Java面试八股文(程序员必备)
    1.面向对象的三大特性?封装:核心思想就是“隐藏细节”,对外提供访问属性的方法。保证了数据的安全和程序的稳定。继承:将子类共性的属性或者方法抽取出来成为父类,子类继承后就不用重复定义父类的属性和方法,只需要扩展自己的个性化。强制继承父类非私有的属性和方法,破坏了封装性原......