java集合知识整理1: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集合。以后我会持续更新每个集合框架更深入的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值