dede免费网站模板utf8,网站开发赚不赚钱,做网站临沂,做网站精英摘要 本篇文章深入探讨了基于JDK 21版本的Java.util包中提供的多样化集合类型。在Java中集合共分类为三种数据结构#xff1a;List、Set和Queue。本文将详细阐述这些数据类型的各自实现#xff0c;并按照线程安全性进行分类#xff0c;分别介绍非线程安全与线程安全的实现方…摘要 本篇文章深入探讨了基于JDK 21版本的Java.util包中提供的多样化集合类型。在Java中集合共分类为三种数据结构List、Set和Queue。本文将详细阐述这些数据类型的各自实现并按照线程安全性进行分类分别介绍非线程安全与线程安全的实现方式。接下来我们将逐一探究这些集合类型的细节和应用。
Collection 图 1 基本集合类图 如图1 所示jdk21 的基本集合类型共包含了三个类分别是Collection 接口、SequencedCollection 接口和 AbstractCollection 抽象类。
Collection Collection 接口是 Java 集合框架中的根接口它定义了集合的基本操作和属性。所有其他集合类型如 List、Set 和 Queue都继承自 Collection 接口。 主要功能 添加元素add(E e)、addAll(Collection? extends E c) 删除元素remove(Object o)、removeAll(Collection? c)、clear() 检查元素contains(Object o)、containsAll(Collection? c) 获取大小size() 迭代元素iterator() 转换为数组toArray()
SequencedCollection SequencedCollection在Jdk21中被引入作为集合框架的拓展。这个接口扩展了 Collection 接口并添加了与顺序相关的方法允许元素按照特定的顺序进行迭代。 主要功能 保持插入顺序SequencedCollection 保证元素的迭代顺序与它们被添加到集合中的顺序相同。 提供顺序相关操作例如first() 和 last() 方法可以分别返回集合中的第一个和最后一个元素。 主要方法 default void addFirst(E e)实现是调用 add(0, e)将元素添加到列表头部存在 null 相关以及不支持操作时的异常情况。 default void addLast(E e)实现是调用 add(e)将元素添加到列表尾部同样有相应异常情况。 default E getFirst()若列表不为空返回 get(0) 的结果否则抛出 NoSuchElementException。 default E getLast()若列表不为空返回 get(size() - 1) 的结果否则抛出 NoSuchElementException。 default E removeFirst()若列表不为空返回 remove(0) 的结果否则抛出 NoSuchElementException也存在不支持操作时的异常情况。 default E removeLast()若列表不为空返回 remove(size() - 1) 的结果否则抛出 NoSuchElementException同样有不支持操作时的异常情况。 default ListE reversed()返回列表的逆序视图以 List 形式呈现委托原列表进行操作。
AbstractCollection AbstractCollection 类是一个抽象类提供了 Collection 接口的基本实现。这个类旨在简化实现自定义集合类型的过程因为它实现了 Collection 接口中的大多数方法只留下 iterator() 和 size() 方法需要子类去实现。 主要特点 作为自定义集合类型的基类通过继承 AbstractCollection可以减少实现一个集合类型所需的工作量。 提供了实用方法比如 addAll()、removeAll()、containsAll() 等这些方法在许多集合类型中是通用的。
在使用 AbstractCollection 时子类必须实现以下两个方法 iterator(): 返回一个迭代器用于遍历集合中的元素。 size(): 返回集合中元素的数量。
List 集合 图2 java-list类型数据结构类图
List 接口 如图2 所示List 接口继承SequencedCollection接口所有的List 拓展数据类型均需要实现List 接口。以下是关于List 接口的重要方法总结。 size返回列表中元素的数量如果元素数量超过 Integer.MAX_VALUE则返回 Integer.MAX_VALUE。 isEmpty若列表不包含任何元素则返回 true反之返回 false。 contains判断列表中是否包含指定元素若存在至少一个元素 e 使得 Objects.equals(o, e) 成立则返回 true否则返回 false。不过在元素类型不兼容或指定元素为 null 列表不允许 null 元素时会抛出相应异常。 iterator返回按正确顺序遍历列表元素的迭代器。 toArray返回一个包含列表所有元素的数组按从第一个到最后一个元素的顺序返回的数组与列表没有引用关联调用者可自由修改该数组起到了数组和集合 API 之间的桥梁作用。 get返回列表中指定位置的元素若索引越界则抛出异常。 set用指定元素替换列表中指定位置的元素返回被替换的原来的元素在不支持替换操作、元素类型不允许、元素为 null 列表不允许时、元素属性不符合要求、索引越界等情况下会抛异常。 add将指定元素追加到列表末尾不同列表实现可能对添加元素有限制在不支持添加操作、元素类型不允许、元素为 null 列表不允许时或元素自身属性不符合要求等情况下会抛出相应异常。 remove若列表中存在指定元素则移除其第一次出现的位置对应的元素若列表不包含该元素则列表不变移除成功返回 true否则返回 false同样在元素类型不兼容或指定元素为 null 列表不允许 null 元素时会抛出异常并且若不支持移除操作也会抛异常。 containsAll判断列表是否包含指定集合中的所有元素在元素类型不兼容、指定集合包含 null 元素列表不允许时或集合本身为 null 等情况下会抛异常。 addAll将指定集合中的所有元素按其迭代器返回的顺序追加到列表末尾若在操作过程中指定集合被修改则行为未定义在不支持添加操作、元素类型不允许、集合包含 null 元素列表不允许时或元素自身属性不符合要求等情况会抛异常。 removeAll从列表中移除所有包含在指定集合中的元素在不支持移除操作、元素类型不兼容、列表含 null 元素指定集合不允许时或集合为 null 等情况会抛异常。 replaceAll使用给定操作符对列表的每个元素进行替换若列表不可修改、操作符为 null 或者操作结果为 null 列表不允许 null 元素时会抛异常。 sort根据指定的比较器对列表进行排序排序是稳定的要求列表元素能用指定比较器相互比较在比较出现类型不兼容、列表迭代器不支持 set 操作、比较器违反相关约定等情况下会抛异常。 clear移除列表中的所有元素若不支持该清除操作则会抛出异常。 indexOf返回指定元素在列表中第一次出现的索引如果列表不包含该元素则返回 -1在元素类型不兼容或指定元素为 null 列表不允许 null 元素时会抛异常。 lastIndexOf返回指定元素在列表中最后一次出现的索引如果列表不包含该元素则返回 -1同样在元素类型不兼容或指定元素为 null 列表不允许 null 元素时会抛异常。 subList返回列表中指定范围含 fromIndex不含 toIndex的视图返回的列表由原列表支持两者的非结构性变化会相互影响若原列表进行了非通过返回列表的结构性修改则语义会未定义端点索引值非法时抛出异常。 spliterator()创建一个用于遍历列表元素的分割迭代器有不同的创建逻辑取决于列表是否是 RandomAccess 等情况并且默认实现额外报告了一些特性。 of返回一个包含X个元素的不可修改列表从 Java 9 起可用。 copyOf返回一个包含给定集合元素的不可修改列表按集合迭代顺序集合不能为 null 且不能包含 null 元素从 Java 10 起可用若给定集合本身是不可修改列表通常不会创建副本。
AbstractList AbstractList是一个抽象类它实现了List接口的大部分方法为具体的列表实现类提供了一个基础框架。通过继承AbstractList开发人员可以更方便地创建自定义的列表类只需关注需要特殊实现的方法即可。
AbstractSequentialList 该类主要侧重于顺序访问元素的列表实现。与AbstractList更侧重于随机访问列表不同AbstractSequentialList假定列表的访问通常是顺序进行的例如通过迭代器逐个元素地访问而不是通过索引进行随机访问。
ArrayList ArrayList是基于数组实现的动态列表它是Java集合框架中最常用的列表类之一。可以存储任意类型的对象并且能够自动调整大小以适应元素的添加和删除。 主要特点 随机访问高效由于其内部是基于数组实现的所以支持快速的随机访问。通过索引访问元素的时间复杂度为。例如使用get(int index)方法获取指定索引位置的元素非常高效。 动态扩容当添加元素时如果数组已满ArrayList会自动创建一个更大的新数组并将原有元素复制到新数组中。例如初始容量为 10当添加第 11 个元素时会创建一个新的更大的数组来存储元素。 顺序存储元素在内存中是顺序存储的这使得遍历元素比较高效。可以使用普通的for循环或者增强型for循环来遍历ArrayList中的元素。 适用场景 适用于需要频繁进行随机访问和遍历操作的场景。比如在数据查询较多而插入和删除操作相对较少的情况下如存储用户信息列表在需要根据用户 ID假设用户 ID 是列表索引快速获取用户信息时ArrayList是一个很好的选择。
LinkedList LinkedList是一个双向链表实现的列表它实现了List接口同时也实现了Deque接口因此可以作为队列、双端队列和栈来使用。 主要特点 高效的插入和删除操作非随机访问在链表中插入和删除元素的操作比较高效。例如在链表中间插入一个元素只需要修改相邻节点的引用即可时间复杂度为不考虑查找插入位置的时间。 双端操作支持作为双端队列它提供了在头部和尾部添加、删除元素的方法如addFirst()、addLast()、removeFirst()、removeLast()等方便在两端进行操作。 顺序访问特性遍历链表需要从头部或尾部开始逐个节点访问不支持像ArrayList那样的随机访问。通过迭代器或者for循环遍历链表的时间复杂度为其中n是链表的长度。 适用场景 适用于需要频繁进行插入和删除操作特别是在列表两端进行操作的场景。例如在实现一个任务队列时新任务可以添加到队列尾部而当任务完成时可以从队列头部移除任务LinkedList可以很好地满足这种需求。
线程安全的List
Vector Deprecated Vector 是Java 早期线程安全的List 实现。Vector的方法都被synchronized关键字修饰在多线程环境下可以保证数据的一致性和完整性同一时刻只有一个线程能够访问和修改Vector中的元素。在现代的java开发中更推荐使用java.util.concurrent包中的数据结构和方法来实现线程安全的List集合。
Stack (Deprecated) Stack类是基于Vector实现的后进先出LIFO的数据结构它继承自Vector并在Vector的基础上提供了专门用于栈操作的方法。不过在 Java 6 之后推荐使用Deque接口及其实现类如ArrayDeque来实现栈的功能因为它们提供了更简洁和一致的栈操作方法。
CopyOnWriteArrayList CopyOnWriteArrayList是java.util.concurrent包中的一个类它实现了List接口用于在多线程环境下提供线程安全的列表操作。其核心原理是 “写时复制”Copy - On - Write。 当对列表进行修改操作如添加、删除或设置元素时它会先复制一份当前的数组底层存储结构是数组然后在这个新的副本数组上进行修改操作。修改完成后再将内部的数组引用指向新的数组。而读取操作是在原始数组上进行的不需要进行加锁操作这样就可以实现高并发的读操作。
线程安全特性
并发读操作的高效性在多个线程同时读取CopyOnWriteArrayList中的元素时由于读操作不需要加锁所以可以同时进行大大提高了读取的效率。例如在一个多线程的 Web 服务器中多个线程可能需要同时读取配置信息列表CopyOnWriteArrayList可以很好地支持这种高并发的读取场景。写操作的线程安全保证在进行写操作时虽然会涉及到数组的复制和修改但通过这种 “写时复制” 机制保证了同一时刻只有一个写操作在进行避免了多个线程同时修改数据而导致的数据不一致问题。例如当一个线程在添加元素时其他线程要么在读取原始数组此时还未更新引用要么在等待当前写操作完成后再进行自己的操作。
适用场景
读多写少的场景因为读操作不需要加锁所以在读取操作远远多于写入操作的情况下CopyOnWriteArrayList能够提供很好的性能。比如在一个系统中配置信息列表被多个线程频繁读取但很少被修改使用CopyOnWriteArrayList就非常合适。遍历操作的稳定性需求场景在遍历列表的过程中如果不希望受到其他线程修改操作的影响CopyOnWriteArrayList是一个不错的选择。因为遍历是在原始数组上进行的即使其他线程正在进行写操作也不会干扰当前的遍历操作保证了遍历数据的稳定性。
局限性
内存占用由于写操作需要复制数组这可能会导致内存占用较大。如果列表中的元素数量很大每次写操作的复制成本就会很高。例如一个包含大量数据的列表频繁进行写操作会消耗大量的内存来存储复制后的数组。数据实时性稍差因为读取操作是基于原始数组的在写操作完成之前读取的可能是旧的数据。对于对数据实时性要求极高的场景可能不太适用。比如在一个实时数据处理系统中要求数据修改后能立即被读取到最新值CopyOnWriteArrayList可能无法满足这种需求。
参考文献
java集合超详解-腾讯云开发者社区-腾讯云
豆包
相关文章推荐
Wend看源码-Java-集合学习(Set)-CSDN博客Wend看源码-Java-集合学习(Queue)-CSDN博客