1. 什么是 Apache Commons Collections4?
Apache Commons Collections4 是一个强大的库,扩展了 Java 标准集合框架,提供了更复杂的集合操作。对于一年左右经验的 Java 开发者,它能帮助你更方便地处理双向映射、自动排序、过滤等功能,这些在标准集合类中很难实现。
2. 如何引入 Apache Commons Collections4?
通过 Maven 引入依赖:
xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
3. 主要功能介绍
3.1. 双向 Map (BidiMap)
BidiMap
是 Apache Commons Collections 中提供的一种双向映射结构,允许你不仅可以通过 key 查找 value,还可以通过 value 查找 key。相比于 Java 标准库中的 HashMap
,它提供了双向查找的能力,非常适合用于需要频繁进行 key-value 对称操作的场景。常见的实现包括:
- DualHashBidiMap :使用
HashMap
实现的双向 Map,适合大多数通用场景,查找性能优异。 - DualLinkedHashBidiMap :基于
LinkedHashMap
的实现,维护插入顺序的双向映射。 - TreeBidiMap :基于
TreeMap
,支持按自然顺序或自定义比较器排序的双向映射。
常见用法
3.1.1 插入和查找操作
BidiMap
的基础操作和普通的 Map
类似,但可以通过 getKey()
方法进行反向查找。
java
BidiMap<String, String> bidiMap = new DualHashBidiMap<>();
bidiMap.put("a", "1");
bidiMap.put("b", "2");
System.out.println(bidiMap.get("a")); // 输出 "1"
System.out.println(bidiMap.getKey("2")); // 输出 "b"
3.1.2 删除操作
在 BidiMap
中,删除元素时会同时删除对应的 key 和 value。
java
bidiMap.removeValue("1"); // 同时移除 key "a" 和 value "1"
实现对比
- DualHashBidiMap:不保证顺序,但性能优越,适合大多数需要高效查找和插入的场景。
- DualLinkedHashBidiMap:维护插入顺序,适合对顺序有要求的场景,如日志或展示数据。
- TreeBidiMap:适用于需要排序的场景,如按字母顺序展示数据或构建有序索引。
应用场景
- 编码与解码:在某些需要双向转换的场景中非常有用,如字母与摩尔斯电码的双向映射。
- 数据库主键和业务键映射:你可能需要一个映射关系,同时能够通过主键查找业务键,反之亦然。
- 缓存:可以用于缓存系统中快速查找值和反向查找。
3.2. 有序 Map 和 Set
Apache Commons Collections4 提供了一些额外的有序 Map
和 Set
实现,它们扩展了 Java 原生集合类型的功能,特别是在排序和双向映射等方面。以下是它们的详细说明:
3.2.1 有序 Map
3.2.1.1 双向排序 Map
-
DualTreeBidiMap :这是一个基于
TreeMap
实现的双向Map
,它不仅允许根据键来排序,还可以根据值来排序。DualTreeBidiMap
保证了键和值的唯一性,并且提供了快速的键值对反转操作。用法示例:
javaBidiMap<String, Integer> bidiMap = new DualTreeBidiMap<>(); bidiMap.put("apple", 1); bidiMap.put("banana", 2); bidiMap.put("cherry", 3); System.out.println(bidiMap); // {apple=1, banana=2, cherry=3} System.out.println(bidiMap.inverseBidiMap()); // {1=apple, 2=banana, 3=cherry}
主要特性:
- 按键和值的自然顺序进行排序。
- 可以通过
inverseBidiMap()
获取反向映射。
3.2.1.2 按插入顺序的双向 Map
-
LinkedMap :这是一个在 Apache Commons Collections4 中的有序
Map
,类似于LinkedHashMap
,它维护了插入顺序。与LinkedHashMap
不同的是,LinkedMap
具有额外的遍历功能和方法,如getFirstKey()
和getLastKey()
,可以快速获取第一个和最后一个键。用法示例:
java
Map<String, Integer> linkedMap = new LinkedMap<>();
linkedMap.put("one", 1);
linkedMap.put("two", 2);
linkedMap.put("three", 3);
System.out.println(linkedMap); // {one=1, two=2, three=3}
System.out.println(linkedMap.getFirstKey()); // one
System.out.println(linkedMap.getLastKey()); // three
主要特性:
- 维护插入顺序。
- 提供
getFirstKey()
和getLastKey()
等便捷方法
3.2.1.3 MultiKeyMap
-
MultiKeyMap<K, V>
:这个类允许将多个键组合起来映射到一个值上。它对多个键的顺序也进行了维护,类似于Map<K, List<V>>
的更高效实现,特别适用于组合键需要有序的情况。用法示例:
javaMultiKeyMap<String, Integer> multiKeyMap = new MultiKeyMap<>(); multiKeyMap.put("apple", "red", 1); multiKeyMap.put("banana", "yellow", 2); System.out.println(multiKeyMap.get("apple", "red")); // 1 System.out.println(multiKeyMap.get("banana", "yellow")); // 2
3.2.1.4 有序 Map 的应用场景
Apache Commons Collections4 提供的有序 Map
更适合以下场景:
- 复杂的双向排序映射 :
DualTreeBidiMap
适用于需要双向映射的场景,并且能够同时保持键和值的自然顺序。 - 需要快速获取首尾元素的场景 :
LinkedMap
提供了快速获取第一个和最后一个元素的能力,适合 FIFO、LRU 缓存等应用场景。 - 多键组合场景 :
MultiKeyMap
对多个键的管理和有序性进行扩展,适合多字段联合索引的情况。
3.2.2 有序 Set
3.2.2.1 双向排序 Set
-
TreeSortedSet :基于
TreeSet
的扩展,TreeSortedSet
维护元素的自然顺序或者自定义顺序,提供与SortedSet
类似的操作。同时,它能够与双向BidiMap
配合使用,以保证键和值的顺序统一。用法示例:
javaSortedSet<String> sortedSet = new TreeSortedSet<>(); sortedSet.add("apple"); sortedSet.add("banana"); sortedSet.add("cherry"); System.out.println(sortedSet); // [apple, banana, cherry]
3.2.2.2 按插入顺序的 Set
-
ListOrderedSet :这是一个维护元素插入顺序的
Set
,它是Set
和List
的组合,内部通过ArrayList
来维护顺序。适用于希望保持元素唯一且按插入顺序迭代的场景。用法示例:
javaSet<String> orderedSet = new ListOrderedSet<>(new HashSet<>()); orderedSet.add("one"); orderedSet.add("two"); orderedSet.add("three"); System.out.println(orderedSet); // [one, two, three]
3.2.2.3 有序 Set 的应用场景
- 按顺序操作的数据集合 :
TreeSortedSet
适合需要根据自然顺序排序的集合操作。 - 有序唯一元素集合 :
ListOrderedSet
适用于插入顺序很重要并且需要保证元素唯一性的场景。
3.2.3 有序 Map 和 Set 的对比
特性 | DualTreeBidiMap | LinkedMap | MultiKeyMap | TreeSortedSet | ListOrderedSet |
---|---|---|---|---|---|
顺序类型 | 键和值的自然顺序 | 插入顺序 | 多键的插入顺序 | 元素的自然顺序 | 插入顺序 |
底层数据结构 | 红黑树 | HashMap + 双向链表 |
Map 组合 |
红黑树 | ArrayList + Set |
适用场景 | 双向映射与排序 | 需要获取首尾元素的场景 | 需要多键组合映射的场景 | 需要排序的集合操作 | 插入顺序的唯一集合操作 |
时间复杂度 | O(log n) 查找、插入 | O(1) 查找、插入 | O(1) 查找、插入 | O(log n) 查找、插入 | O(1) 查找、插入 |
3.3. Bag
Bag
是 Apache Commons Collections4 提供的一种特殊集合,它允许在集合中存储相同元素的多个实例,并记录每个元素的出现次数。Bag
是对 Java 标准集合的一种扩展,适合用于处理多重集合或计数集合。Commons Collections4 中的 Bag
提供了多种实现,并有不同的优化特性。
3.3.1 Bag 接口
Bag
接口继承自 Collection
,提供了额外的方法来处理元素的计数。与 Set
不同,Bag
允许存储相同元素的多个实例,但与 List
不同,Bag
关注的是元素的频率而非顺序。常用的方法包括:
add(E object, int n)
:添加n
个给定的对象。getCount(Object object)
:获取给定对象的出现次数。remove(Object object, int n)
:删除指定数量的对象实例。
3.3.2 Bag 实现
Commons Collections4 提供了几种不同的 Bag
实现,针对不同的使用场景和性能需求:
3.3.2.1 HashBag
HashBag
基于 HashMap
实现,提供了高效的插入、删除和计数操作。它是一个无序的 Bag
,适合不关心元素顺序的场景。HashBag
是最常用的 Bag
实现,具有较高的性能。
用法示例:
java
Bag<String> bag = new HashBag<>();
bag.add("apple", 3); // 添加 3 个 "apple"
bag.add("banana", 2); // 添加 2 个 "banana"
System.out.println(bag.getCount("apple")); // 输出 3
System.out.println(bag); // 输出 [apple, apple, apple, banana, banana]
3.3.2.2 TreeBag
TreeBag
是 Bag
的有序实现,基于 TreeMap
,它确保元素按自然顺序或提供的比较器顺序进行存储。适合需要排序并统计元素出现次数的场景。
用法示例:
java
Bag<String> treeBag = new TreeBag<>();
treeBag.add("cherry", 2);
treeBag.add("apple", 3);
System.out.println(treeBag); // 输出 [apple, apple, apple, cherry, cherry]
主要特性:
- 元素自动排序(自然顺序或自定义顺序)。
- 时间复杂度为 O(log n)。
3.3.2.3 SynchronizedBag
SynchronizedBag
是线程安全的 Bag
实现,它通过对底层 Bag
进行包装,提供同步操作。适合多线程并发访问的场景。
用法示例:
java
Bag<String> syncBag = SynchronizedBag.synchronizedBag(new HashBag<>());
syncBag.add("apple", 1);
3.3.2.4 PredicatedBag
PredicatedBag
是一个带有过滤条件的 Bag
,它确保只有满足特定条件的元素才能被添加到 Bag
中。适合需要约束集合元素的场景。
用法示例:
java
Predicate<String> noNull = Objects::nonNull;
Bag<String> predicatedBag = PredicatedBag.predicatedBag(new HashBag<>(), noNull);
predicatedBag.add("apple"); // 成功
predicatedBag.add(null); // 抛出 IllegalArgumentException
3.3.2.5 TransformedBag
TransformedBag
是一个带有转换功能的 Bag
,它会在元素添加到集合之前对其进行转换操作。适合需要在集合中存储规范化数据的场景。
用法示例:
java
Bag<String> transformedBag = TransformedBag.transformingBag(new HashBag<>(), String::toLowerCase);
transformedBag.add("APPLE");
System.out.println(transformedBag); // 输出 [apple]
3.3.3 Bag 应用场景
Bag
的主要应用场景包括:
- 元素计数 :当需要统计元素在集合中的出现次数时,
Bag
是比Map<E, Integer>
更合适的选择。 - 多重集合操作:适合需要存储同一元素的多个实例的场景。
- 频率分析:可以用于对数据进行频率分析,如词频统计、事件计数等。
3.3.4 Bag 实现对比
特性 | HashBag | TreeBag | SynchronizedBag | PredicatedBag | TransformedBag |
---|---|---|---|---|---|
是否有序 | 否 | 是(自然顺序) | 否(与底层 Bag 一致) |
否(与底层 Bag 一致) |
否(与底层 Bag 一致) |
线程安全性 | 否 | 否 | 是 | 否 | 否 |
自定义元素约束 | 否 | 否 | 否 | 是 | 否 |
元素转换功能 | 否 | 否 | 否 | 否 | 是 |
底层数据结构 | HashMap |
TreeMap |
取决于包装的 Bag 实现 |
取决于包装的 Bag 实现 |
取决于包装的 Bag 实现 |
时间复杂度(增删查) | O(1) | O(log n) | O(1) 或 O(log n) | O(1) 或 O(log n) | O(1) 或 O(log n) |
3.3.5 Bag 的局限性
虽然 Bag
提供了对多重集合的高效支持,但它并不适用于所有场景。需要注意的是:
- 顺序问题 :默认情况下,
Bag
并不维护元素的插入顺序,如果需要顺序性,可以选择TreeBag
或自行管理顺序。 - 线程安全性 :大多数
Bag
实现并非线程安全,除非显式使用SynchronizedBag
。
3.4. IteratorUtils
IteratorUtils
是 Apache Commons Collections4 提供的一个实用工具类,包含了一组静态方法,用于简化和增强 Java 的 Iterator
操作。它提供了多种便捷方法,帮助开发者处理迭代器的创建、组合、过滤和转换等功能。
3.4.1 主要方法
以下是 IteratorUtils
中的一些常用方法:
3.4.1.1 toList(Iterator<? extends T> iterator)
将给定的迭代器转换为 List
。这对于将迭代器的数据转换为更常用的集合类型非常有用。
用法示例:
java
Iterator<String> iterator = Arrays.asList("apple", "banana", "cherry").iterator();
List<String> list = IteratorUtils.toList(iterator);
3.4.1.2 toArray(Iterator<? extends T> iterator)
将迭代器转换为数组。此方法适用于需要将迭代器的内容存储在数组中的场景。
用法示例:
java
Iterator<Integer> iterator = Arrays.asList(1, 2, 3).iterator();
Integer[] array = IteratorUtils.toArray(iterator);
3.4.1.3 emptyIterator()
返回一个空的迭代器。这在需要返回一个空集合的场景中非常有用。
用法示例:
java
Iterator<String> emptyIterator = IteratorUtils.emptyIterator();
3.4.1.4 asIterator(Enumeration<? extends T> enumeration)
将 Enumeration
转换为 Iterator
。此方法在需要将旧版 API 与新 API 进行整合时非常实用。
用法示例:
java
Enumeration<String> enumeration = Collections.enumeration(Arrays.asList("one", "two", "three"));
Iterator<String> iterator = IteratorUtils.asIterator(enumeration);
3.4.1.5 filteredIterator(Iterator<? extends T> iterator, Predicate<? super T> predicate)
返回一个过滤后的迭代器,仅包含满足给定条件的元素。这对于在迭代过程中应用过滤条件非常有用。
用法示例:
java
Iterator<Integer> iterator = Arrays.asList(1, 2, 3, 4).iterator();
Iterator<Integer> filtered = IteratorUtils.filteredIterator(iterator, n -> n % 2 == 0); // 仅保留偶数
3.4.1.6 concatenatedIterator(Iterator<? extends T>... iterators)
将多个迭代器连接成一个迭代器,便于遍历多个集合中的元素。
用法示例:
java
Iterator<String> iterator1 = Arrays.asList("A", "B").iterator();
Iterator<String> iterator2 = Arrays.asList("C", "D").iterator();
Iterator<String> concatenated = IteratorUtils.concatenatedIterator(iterator1, iterator2);
3.4.2 应用场景
- 集合转换:将迭代器内容转换为其他集合类型,简化数据处理。
- 数据过滤:通过过滤条件,精确控制迭代器的输出。
- 迭代器组合:在需要遍历多个集合时,方便地将多个迭代器合并。
3.4.3 IteratorUtils 优势
- 简化代码:减少迭代器处理的样板代码,提高可读性。
- 功能扩展:提供标准 Java 集合库没有的功能,如过滤和合并迭代器。
- 兼容性 :支持将
Enumeration
转换为Iterator
,方便与旧版代码集成。
3.4.4 注意事项
- 不支持并发 :
IteratorUtils
的方法未提供对迭代器的并发安全支持,需在单线程环境中使用。 - 懒惰求值:一些方法可能返回一个懒惰求值的迭代器,需注意迭代顺序和数据一致性。
3.5. Transformation 和 Predicate
Transformation
和 Predicate
是 Apache Commons Collections4 中的重要接口,用于实现数据的转换和过滤逻辑。这些接口为处理集合和流提供了灵活的方式,特别是在需要对数据进行处理时。
3.5.1 Transformation
Transformation
接口用于定义一种从输入类型转换为输出类型的操作。它主要用于将集合中的元素进行转换,生成新的集合。
5.1.1 主要方法
- transform(Object input):接收输入对象,并返回转换后的对象。
用法示例:
java
Transformation<String, Integer> transformation = new Transformation<String, Integer>() {
@Override
public Integer transform(String input) {
return input.length(); // 转换为字符串的长度
}
};
5.1.2 使用场景
- 集合转换:将一个集合中的对象转换为另一种类型的集合。
- 数据处理:对集合中的每个元素应用转换逻辑,生成新的数据视图。
5.1.3 例子
使用 CollectionUtils
类中的 collect
方法,将一个字符串集合转换为其长度集合:
java
List<String> strings = Arrays.asList("one", "two", "three");
List<Integer> lengths = (List<Integer>) CollectionUtils.collect(strings, transformation);
3.5.2 Predicate
Predicate
接口用于定义一种条件测试操作,判断给定对象是否满足特定条件。它主要用于过滤集合中的元素。
5.2.1 主要方法
- evaluate(Object object):接收对象并返回布尔值,表示对象是否满足条件。
用法示例:
java
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean evaluate(String input) {
return input.length() > 3; // 判断字符串长度是否大于3
}
};
5.2.2 使用场景
- 集合过滤:从集合中筛选出符合条件的元素。
- 条件逻辑:在复杂逻辑中使用,可嵌套组合多个条件。
5.2.3 例子
使用 CollectionUtils
类中的 select
方法,过滤出长度大于3的字符串:
java
List<String> strings = Arrays.asList("one", "two", "three", "four");
List<String> filtered = (List<String>) CollectionUtils.select(strings, predicate);
3.5.3 组合使用
Transformation
和 Predicate
可以结合使用,首先通过 Predicate
过滤集合,然后使用 Transformation
进行转换。例如,先筛选出符合条件的元素,再将它们转换为另一种类型。
java
List<String> strings = Arrays.asList("one", "two", "three", "four");
Predicate<String> predicate = input -> input.length() > 3;
Transformation<String, Integer> transformation = String::length;
List<Integer> lengths = (List<Integer>) CollectionUtils.collect(
(List<String>) CollectionUtils.select(strings, predicate),
transformation
);
4. 其他实用工具
4.1. CollectionUtils
CollectionUtils
是 Apache Commons Collections4 中的一个工具类,专门用于提供一系列集合操作的静态方法。这些方法简化了常见的集合处理任务,帮助开发者更高效地管理集合。
4.1.1 主要功能
- 空值检查 :验证集合是否为空或为
null
,避免在操作集合时引发NullPointerException
。 - 集合操作:提供对集合的批量添加、合并、过滤和转换等功能。
- 集合比较:支持集合之间的比较,包括交集、并集、差集等操作。
- 集合分割:将一个集合拆分为多个小集合。
4.1.2 常用方法
-
isEmpty(Collection coll) :检查集合是否为空或为
null
。如果集合为null
或没有元素,则返回true
。javaboolean isEmpty = CollectionUtils.isEmpty(myList);
-
addAll(Collection<? super T> coll, T... elements):将指定的元素数组添加到集合中。此方法是一个便捷的方式来批量添加元素。
javaCollectionUtils.addAll(myList, "one", "two", "three");
-
select(Collection collection, Predicate<? super E> predicate) :返回符合条件的元素集合。
Predicate
用于定义筛选条件。javaList<String> filtered = (List<String>) CollectionUtils.select(myList, s -> s.length() > 3);
-
collect(Collection collection, Transformation<? super E, ? extends T> transformation):将集合中的元素通过指定的转换逻辑进行转换,返回新的集合。
javaList<Integer> lengths = (List<Integer>) CollectionUtils.collect(myList, String::length);
-
union(Collection<?> collection1, Collection<?> collection2):返回两个集合的并集,结果包含两个集合中的所有元素。
javaCollection<?> union = CollectionUtils.union(collection1, collection2);
-
intersection(Collection<?> collection1, Collection<?> collection2):返回两个集合的交集,结果只包含两个集合中都存在的元素。
javaCollection<?> intersection = CollectionUtils.intersection(collection1, collection2);
-
subtract(Collection<?> collection1, Collection<?> collection2):返回在第一个集合中存在但不在第二个集合中的元素。
javaCollection<?> difference = CollectionUtils.subtract(collection1, collection2);
-
partition(Collection collection, Predicate<? super E> predicate):根据给定条件将集合分割成两个子集合。
javaMap<Boolean, List<String>> partitioned = CollectionUtils.partition(myList, s -> s.length() > 3);
4.1.3 使用场景
- 空集合处理 :在执行操作前,使用
isEmpty
方法检查集合的状态,防止空指针异常。 - 集合批量操作 :使用
addAll
快速添加多个元素,简化代码。 - 数据筛选 :通过
select
方法对集合进行条件筛选,获取满足特定条件的元素。 - 数据转换 :利用
collect
方法将集合元素转换为其他类型,便于后续操作。 - 集合运算 :通过
union
、intersection
和subtract
方法进行集合的基本运算。 - 集合分割:在处理复杂数据时,可以将集合分割为多个小集合进行逐一处理。
4.1.4 例子
以下是一些示例代码,展示如何使用 CollectionUtils
进行集合操作:
java
import org.apache.commons.collections4.CollectionUtils;
List<String> myList = new ArrayList<>(Arrays.asList("one", "two", "three"));
// 判断是否为空
if (CollectionUtils.isEmpty(myList)) {
System.out.println("列表为空");
}
// 批量添加元素
CollectionUtils.addAll(myList, "four", "five");
// 根据条件过滤集合
Predicate<String> predicate = input -> input.length() > 3;
List<String> filtered = (List<String>) CollectionUtils.select(myList, predicate);
// 转换集合元素为其长度
Transformation<String, Integer> transformation = String::length;
List<Integer> lengths = (List<Integer>) CollectionUtils.collect(myList, transformation);
// 获取两个集合的并集
List<String> otherList = Arrays.asList("six", "seven");
Collection<?> union = CollectionUtils.union(myList, otherList);
// 获取两个集合的交集
Collection<?> intersection = CollectionUtils.intersection(myList, otherList);
// 获取两个集合的差集
Collection<?> difference = CollectionUtils.subtract(myList, otherList);
// 根据条件将集合分割为两个子集合
Map<Boolean, List<String>> partitioned = CollectionUtils.partition(myList, s -> s.length() > 3);
4.2. Predicate 和 Closure
Predicate
和 Closure
是 Apache Commons Collections4 中提供的两个重要概念,旨在简化集合操作,提升代码的可读性和灵活性。
4.2.1 Predicate
Predicate
是一个函数式接口,表示一个接受单个输入参数并返回布尔值的逻辑条件。它通常用于过滤集合中的元素。
主要功能
- 条件筛选 :使用
Predicate
定义筛选条件,结合集合操作方法(如select
和removeIf
),从集合中选择或删除符合条件的元素。 - 组合条件 :支持将多个
Predicate
组合在一起,形成复杂的条件逻辑。
常用方法
- test(T t) :接受一个输入参数,返回
true
或false
,用于判断该参数是否符合条件。
java
Predicate<String> isLongerThanThree = str -> str.length() > 3;
boolean result = isLongerThanThree.test("Hello"); // true
使用场景
- 集合过滤 :在处理集合时,可以使用
Predicate
对集合中的元素进行条件筛选。
java
List<String> myList = Arrays.asList("one", "two", "three", "four");
List<String> filteredList = (List<String>) CollectionUtils.select(myList, isLongerThanThree);
4.2.2 Closure
Closure
是另一个函数式接口,表示一个接受输入参数并不返回值的操作。它通常用于对集合中的每个元素执行某种操作。
主要功能
- 操作执行:允许对集合中的每个元素执行特定的操作(例如打印、修改等)。
- 无需返回值 :与
Predicate
不同,Closure
不需要返回值,可以用于执行副作用操作。
常用方法
- execute(T input):接受一个输入参数,对其执行某种操作,通常用于副作用逻辑。
java
Closure<String> printClosure = str -> System.out.println(str);
printClosure.execute("Hello, World!"); // 输出 "Hello, World!"
使用场景
- 集合遍历 :在遍历集合时,可以使用
Closure
对每个元素执行操作,而无需关心返回值。
java
List<String> myList = Arrays.asList("one", "two", "three");
CollectionUtils.forAllDo(myList, printClosure); // 输出每个元素
4.2.3 示例代码
以下示例展示了如何使用 Predicate
和 Closure
进行集合操作:
java
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.Closure;
import java.util.Arrays;
import java.util.List;
public class PredicateClosureExample {
public static void main(String[] args) {
List<String> myList = Arrays.asList("one", "two", "three", "four");
// 使用 Predicate 过滤集合
Predicate<String> isLongerThanThree = str -> str.length() > 3;
List<String> filteredList = (List<String>) CollectionUtils.select(myList, isLongerThanThree);
System.out.println("Filtered List: " + filteredList); // 输出: [four]
// 使用 Closure 打印集合中的元素
Closure<String> printClosure = str -> System.out.println(str);
CollectionUtils.forAllDo(myList, printClosure);
}
}
4.3. MultiMap
MultiMap
是 Apache Commons Collections4 提供的一种特殊的集合,它允许一个键映射到多个值。与标准的 Map
不同,MultiMap
解决了多个值存储的问题,使得在存储和操作关联数据时更加高效和便捷。
4.3.1 基本概念
- 键-值对 :在
MultiMap
中,键是唯一的,而每个键可以关联多个值。这种特性使得它非常适合于处理一对多的关系。 - 值的集合 :每个键的值通常存储在一个集合中,如
List
或Set
,允许重复值或不重复值的选择。
4.3.2 实现类
Apache Commons Collections4 提供了几种实现 MultiMap
接口的具体类,包括:
- ListMultiMap :每个键映射到一个
List
,允许重复值。 - SetMultiMap :每个键映射到一个
Set
,不允许重复值。 - BagMultiMap :每个键映射到一个
Bag
,允许重复值,并提供元素计数功能。
4.3.3 常用方法
MultiMap
接口提供了一些基本的方法,便于操作键和值:
- put(K key, V value):将值添加到指定键的值集合中。如果键不存在,则会创建一个新的值集合。
- remove(K key, V value):从指定键的值集合中移除给定值。如果值集合为空,则键也会被删除。
- get(K key):获取与指定键关联的值集合。
- keySet() :返回
MultiMap
中所有的键。 - values() :返回
MultiMap
中所有的值集合。
4.3.4 示例代码
以下示例演示了如何使用 MultiMap
进行常见操作:
java
import org.apache.commons.collections4.MultiMap;
import org.apache.commons.collections4.MultiValuedMap;
import org.apache.commons.collections4.list.SetUniqueList;
import java.util.List;
public class MultiMapExample {
public static void main(String[] args) {
// 创建一个 ListMultiMap 实例
MultiValuedMap<String, String> multiMap = MultiValuedMap.multiValuedMap();
// 添加值
multiMap.put("Fruit", "Apple");
multiMap.put("Fruit", "Banana");
multiMap.put("Fruit", "Apple"); // 允许重复
multiMap.put("Vegetable", "Carrot");
// 获取与键关联的值集合
List<String> fruits = (List<String>) multiMap.get("Fruit");
System.out.println("Fruits: " + fruits); // 输出: Fruits: [Apple, Banana, Apple]
// 移除特定值
multiMap.remove("Fruit", "Apple");
System.out.println("Fruits after removal: " + fruits); // 输出: Fruits after removal: [Banana, Apple]
// 遍历所有键和值
for (String key : multiMap.keySet()) {
System.out.println("Key: " + key + ", Values: " + multiMap.get(key));
}
}
}
4.3.5 使用场景
MultiMap
在以下场景中非常有用:
- 一对多关系:当一个实体需要关联多个值时,例如学生和他们的课程、用户和他们的地址等。
- 数据分组 :在处理分组数据时,可以使用
MultiMap
来轻松管理和访问分组内的所有元素。 - 简化数据结构 :避免使用嵌套的
Map
和List
,通过MultiMap
简化数据结构,提高代码的可读性。
4.4. ListUtils
ListUtils
是 Apache Commons Collections4 提供的一个工具类,专门用于操作 List
集合。该类包含了多个静态方法,方便开发者进行常见的列表操作,如合并、排序、查找、过滤等。
4.4.1 基本功能
-
合并列表:
- union:返回两个列表的合并结果,去除重复元素。
- intersection:返回两个列表的交集,包含出现在两个列表中的元素。
- subtract:返回第一个列表中存在但在第二个列表中不存在的元素。
- disjunction:返回两个列表的对称差集,即只出现在其中一个列表中的元素。
-
查找和过滤:
- select:根据给定的条件过滤列表,返回满足条件的子集。
- reject :与
select
相反,返回不满足条件的子集。 - indexOf :查找某个元素在列表中的索引,若不存在则返回
-1
。 - lastIndexOf:查找某个元素最后一次出现的索引。
-
列表操作:
- reverse:反转列表的元素顺序。
- rotate:将列表的元素循环移动指定的次数。
- toArray:将列表转换为数组。
-
组合与分组:
- partition:将列表分成固定大小的多个子列表。
- collate:合并两个已排序的列表,返回一个新的排序列表。
-
其它辅助功能:
- isEmpty:检查列表是否为空。
- addAll:将多个元素添加到列表中。
- removeAll:从列表中移除多个元素。
4.4.2 示例代码
以下示例展示了 ListUtils
的一些常用方法:
java
import org.apache.commons.collections4.ListUtils;
import java.util.Arrays;
import java.util.List;
public class ListUtilsExample {
public static void main(String[] args) {
List<String> list1 = Arrays.asList("Apple", "Banana", "Cherry");
List<String> list2 = Arrays.asList("Banana", "Date", "Fig");
// 合并列表
List<String> union = ListUtils.union(list1, list2);
System.out.println("Union: " + union); // 输出: [Apple, Banana, Cherry, Date, Fig]
// 交集
List<String> intersection = ListUtils.intersection(list1, list2);
System.out.println("Intersection: " + intersection); // 输出: [Banana]
// 差集
List<String> subtract = ListUtils.subtract(list1, list2);
System.out.println("Subtract: " + subtract); // 输出: [Apple, Cherry]
// 对称差集
List<String> disjunction = ListUtils.disjunction(list1, list2);
System.out.println("Disjunction: " + disjunction); // 输出: [Apple, Cherry, Date, Fig]
// 过滤列表
List<String> selected = ListUtils.select(list1, s -> s.startsWith("B"));
System.out.println("Selected: " + selected); // 输出: [Banana]
// 反转列表
List<String> reversed = ListUtils.reverse(list1);
System.out.println("Reversed: " + reversed); // 输出: [Cherry, Banana, Apple]
// 分组
List<List<String>> partitioned = ListUtils.partition(list1, 2);
System.out.println("Partitioned: " + partitioned); // 输出: [[Apple, Banana], [Cherry]]
// 将列表转换为数组
String[] array = ListUtils.toArray(list1, new String[0]);
System.out.println("Array: " + Arrays.toString(array)); // 输出: [Apple, Banana, Cherry]
}
}
4.4.3 使用场景
- 数据处理 :在处理数据集时,合并、交集和差集操作十分常见,使用
ListUtils
可以大大简化代码。 - 过滤与查找 :当需要从大数据集中查找符合条件的数据时,
select
和reject
方法提供了有效的解决方案。 - 列表管理 :管理
List
的顺序和分组,使数据处理更加灵活和高效。
4.5. MapUtils
MapUtils
是 Apache Commons Collections4 提供的一个工具类,专门用于操作 Map
集合。该类包含了多个静态方法,用于简化对 Map
的常见操作,如查找、合并、过滤等。
4.5.1 基本功能
-
安全访问:
- get :根据给定的键从
Map
中安全地获取值。如果键不存在,返回指定的默认值,避免NullPointerException
。 - getWithDefault:返回与键对应的值,如果键不存在则返回指定的默认值。
- get :根据给定的键从
-
空值检查:
- isEmpty :检查
Map
是否为空。 - isNotEmpty :检查
Map
是否不为空。
- isEmpty :检查
-
合并和更新:
- putAll :将另一个
Map
中的所有键值对添加到当前Map
中。 - putIfAbsent :仅在指定的键不存在时,将指定的键值对放入
Map
。
- putAll :将另一个
-
查找和过滤:
- filter :根据给定的条件过滤
Map
中的键值对,返回满足条件的子Map
。 - keySet :返回
Map
中的键的集合。 - values :返回
Map
中的值的集合。
- filter :根据给定的条件过滤
-
转换和比较:
- toString :将
Map
转换为字符串形式,便于调试。 - equals :比较两个
Map
是否相等,支持自定义比较规则。
- toString :将
-
迭代操作:
- forEach :对
Map
的每个键值对执行给定的操作,类似于 Java 8 中的forEach
方法。 - mapIterator :返回
Map
的迭代器,可以遍历Map
中的键值对。
- forEach :对
4.5.2 示例代码
以下示例展示了 MapUtils
的一些常用方法:
java
import org.apache.commons.collections4.MapUtils;
import java.util.HashMap;
import java.util.Map;
public class MapUtilsExample {
public static void main(String[] args) {
Map<String, String> map1 = new HashMap<>();
map1.put("A", "Apple");
map1.put("B", "Banana");
Map<String, String> map2 = new HashMap<>();
map2.put("C", "Cherry");
map2.put("B", "Berry");
// 安全获取值
String value = MapUtils.get(map1, "A", "Default");
System.out.println("Value for key 'A': " + value); // 输出: Apple
// 合并两个 Map
MapUtils.putAll(map1, map2);
System.out.println("Merged Map: " + map1); // 输出: {A=Apple, B=Berry, C=Cherry}
// 空值检查
boolean isEmpty = MapUtils.isEmpty(map1);
System.out.println("Is map1 empty? " + isEmpty); // 输出: false
// 过滤 Map
Map<String, String> filteredMap = MapUtils.filter(map1, (key, value1) -> key.equals("A"));
System.out.println("Filtered Map: " + filteredMap); // 输出: {A=Apple}
// 转换为字符串
String mapString = MapUtils.toString(map1);
System.out.println("Map as String: " + mapString); // 输出: {A=Apple, B=Berry, C=Cherry}
// 遍历 Map
MapUtils.forEach(map1, (key, value1) -> System.out.println(key + " -> " + value1));
// 输出:
// A -> Apple
// B -> Berry
// C -> Cherry
}
}
4.5.3 使用场景
- 数据管理 :在处理配置或数据存储时,使用
Map
可以方便地查找和存储键值对。 - 合并操作 :将多个数据源合并为一个
Map
,例如在从数据库获取数据后合并成一个配置Map
。 - 过滤和查找:快速获取符合特定条件的子集,如查找所有特定前缀的键。
- 安全访问 :避免在获取值时出现
NullPointerException
,提供默认值处理。
4.6. QueueUtils
QueueUtils
是 Apache Commons Collections4 中提供的一个工具类,专注于操作 Queue
集合。该类包含多个静态方法,用于简化对 Queue
的常见操作,如添加、移除、查询等。
4.6.1 基本功能
-
安全操作:
- add:将指定元素添加到队列中,如果队列已满,则抛出异常。
- offer :尝试将指定元素添加到队列中。如果队列已满,返回
false
,而不抛出异常。 - remove:从队列中移除并返回头元素,如果队列为空则抛出异常。
- poll :从队列中移除并返回头元素,如果队列为空,则返回
null
。
-
查询操作:
- peek :查看但不移除队列的头元素,如果队列为空,则返回
null
。 - size:获取队列中的元素数量。
- peek :查看但不移除队列的头元素,如果队列为空,则返回
-
遍历和集合操作:
- forEach :对
Queue
中的每个元素执行给定的操作,类似于 Java 8 中的forEach
方法。 - toArray:将队列转换为数组,支持指定数组类型。
- isEmpty:检查队列是否为空。
- forEach :对
-
集合转换:
- asQueue :将一个普通的集合(如
Collection
)转换为Queue
,以便于使用队列特有的操作。
- asQueue :将一个普通的集合(如
-
顺序管理:
- toString:将队列转换为字符串形式,便于调试和查看。
4.6.2 示例代码
以下示例展示了 QueueUtils
的一些常用方法:
java
import org.apache.commons.collections4.QueueUtils;
import java.util.LinkedList;
import java.util.Queue;
public class QueueUtilsExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// 添加元素
QueueUtils.add(queue, "Element 1");
QueueUtils.add(queue, "Element 2");
System.out.println("Queue after adding elements: " + queue); // 输出: [Element 1, Element 2]
// 使用 offer 方法
boolean added = QueueUtils.offer(queue, "Element 3");
System.out.println("Was Element 3 added? " + added); // 输出: true
// 查询头元素
String headElement = QueueUtils.peek(queue);
System.out.println("Head element: " + headElement); // 输出: Element 1
// 移除头元素
String removedElement = QueueUtils.remove(queue);
System.out.println("Removed element: " + removedElement); // 输出: Element 1
System.out.println("Queue after removal: " + queue); // 输出: [Element 2, Element 3]
// 获取队列大小
int size = QueueUtils.size(queue);
System.out.println("Queue size: " + size); // 输出: 2
// 遍历队列
QueueUtils.forEach(queue, element -> System.out.println("Queue element: " + element));
// 输出:
// Queue element: Element 2
// Queue element: Element 3
// 检查是否为空
boolean isEmpty = QueueUtils.isEmpty(queue);
System.out.println("Is queue empty? " + isEmpty); // 输出: false
// 转换为数组
String[] array = QueueUtils.toArray(queue, new String[0]);
System.out.println("Queue as array: " + String.join(", ", array)); // 输出: Element 2, Element 3
}
}
4.6.3 使用场景
- 任务队列管理:在并发编程或任务调度中,使用队列来管理任务的执行顺序。
- 事件处理:在事件驱动的系统中,使用队列来缓存待处理的事件。
- 流控制:在数据流的应用中,使用队列来控制数据的流入和流出,避免数据丢失。
4.7. IterableMap 和 OrderedMap
4.7.1 IterableMap
IterableMap
是 Apache Commons Collections4 中定义的一个接口,它扩展了 Java 的 Map
接口,并添加了一些迭代功能。此接口允许开发者通过 Iterable
接口来遍历映射的条目,而不仅仅是通过传统的 entrySet()
、keySet()
或 values()
方法。
主要特性:
- 迭代访问 :可以直接对映射中的条目进行迭代。
IterableMap
提供了iterator()
方法,返回一个Iterator
,可以遍历映射中的条目。 - 增强的可读性:使代码更简洁,通过增强的迭代支持,减少了不必要的转换步骤。
主要方法:
Iterator<Entry<K, V>> iterator()
:返回一个迭代器,用于遍历映射的条目。
示例代码:
java
import org.apache.commons.collections4.IterableMap;
import org.apache.commons.collections4.map.LinkedMap;
public class IterableMapExample {
public static void main(String[] args) {
IterableMap<String, Integer> map = new LinkedMap<>();
map.put("One", 1);
map.put("Two", 2);
map.put("Three", 3);
for (Entry<String, Integer> entry : map) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
4.7.2 OrderedMap
OrderedMap
是 Apache Commons Collections4 中的另一个接口,扩展了 Map
接口,并提供了按插入顺序维护条目的能力。该接口确保当你遍历 OrderedMap
的时候,条目的顺序与它们被插入的顺序相同。
主要特性:
- 插入顺序:保证条目的顺序与插入顺序一致,便于处理需要有序数据的场景。
- 支持双向访问 :可以通过
List
的方式访问映射中的条目,也可以通过Map
的方式访问,增强了灵活性。
主要方法:
List<K> keys()
:返回一个按插入顺序排列的键的列表。List<V> values()
:返回一个按插入顺序排列的值的列表。List<Entry<K, V>> entries()
:返回一个按插入顺序排列的条目列表。
示例代码:
java
import org.apache.commons.collections4.OrderedMap;
import org.apache.commons.collections4.map.LinkedMap;
public class OrderedMapExample {
public static void main(String[] args) {
OrderedMap<String, Integer> orderedMap = new LinkedMap<>();
orderedMap.put("One", 1);
orderedMap.put("Two", 2);
orderedMap.put("Three", 3);
System.out.println("Keys in order of insertion: " + orderedMap.keys());
System.out.println("Values in order of insertion: " + orderedMap.values());
for (Entry<String, Integer> entry : orderedMap.entries()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
4.7.3 使用场景
- 需要保持顺序的映射:在处理数据时,需要确保映射中的条目以插入顺序进行处理的场景,如配置参数、历史记录等。
- 便于迭代访问 :在需要遍历映射中的所有条目时,
IterableMap
的设计使得操作更加简洁。
4.8. Trie
Trie
是一种树形数据结构,用于高效存储和检索字符串,尤其适用于前缀匹配的场景。Apache Commons Collections4 提供了 Trie
接口和相关实现,允许开发者使用 Trie 结构来存储字符串集合。
4.8.1 主要特性
- 前缀搜索:能够快速查找以某个前缀开头的字符串,这使得 Trie 在自动补全和拼写检查等应用中非常有效。
- 空间效率:Trie 通过共享公共前缀来节省内存,与单独存储每个字符串相比,具有更好的空间效率。
- 动态插入和删除:Trie 支持动态添加和删除字符串,这对于需要频繁更新的数据集非常有用。
4.8.2 主要方法
以下是 Trie
接口中的一些主要方法:
void insert(String word)
:将一个字符串插入到 Trie 中。boolean contains(String word)
:检查 Trie 中是否包含某个字符串。List<String> autocomplete(String prefix)
:返回以给定前缀开头的所有字符串列表。void delete(String word)
:从 Trie 中删除一个字符串。
4.8.3 实现示例
以下是使用 Trie
的简单示例,展示如何插入字符串、检查是否存在以及进行前缀匹配。
java
import org.apache.commons.collections4.trie.PatriciaTrie;
public class TrieExample {
public static void main(String[] args) {
PatriciaTrie<String> trie = new PatriciaTrie<>();
// 插入字符串
trie.put("apple", "A fruit");
trie.put("app", "A short form of application");
trie.put("apricot", "Another fruit");
// 检查是否包含某个字符串
System.out.println("Contains 'apple'? " + trie.containsKey("apple")); // true
System.out.println("Contains 'banana'? " + trie.containsKey("banana")); // false
// 前缀匹配
String prefix = "app";
List<String> suggestions = new ArrayList<>(trie.prefixMap(prefix).keySet());
System.out.println("Autocomplete suggestions for '" + prefix + "': " + suggestions);
}
}
4.8.4 使用场景
- 自动补全:在输入框中,实时给出用户可能输入的选项。
- 拼写检查:根据用户输入,给出正确的拼写建议。
- 字典实现:用于词汇表、搜索引擎中的关键词管理等。
4.8.5 性能
- 插入时间复杂度:O(m),其中 m 是插入字符串的长度。
- 搜索时间复杂度:O(m),其中 m 是搜索字符串的长度。
- 空间复杂度:取决于插入的字符串数量及其共同前缀。
Trie
在处理大量字符串时表现出色,特别是当应用程序需要支持高效的前缀搜索时,选择 Trie
结构将极大提高性能。
4.9. ComparatorUtils
ComparatorUtils
是 Apache Commons Collections4 中的一个工具类,提供了一系列静态方法,用于创建和组合比较器(Comparator
)。它简化了比较对象的操作,支持各种排序需求。
4.9.1 主要特性
- 组合比较器:能够将多个比较器组合成一个,从而支持多级排序。
- 空值处理:提供了对空值的自定义处理选项。
- 简化的比较器创建:提供了各种方法来快速创建常见的比较器。
4.9.2 主要方法
以下是 ComparatorUtils
中的一些重要方法:
-
Comparator<T> nullsFirst(Comparator<T> comparator)
:返回一个比较器,该比较器在比较时将空值排在前面。javaComparator<String> comparator = ComparatorUtils.nullsFirst(Comparator.naturalOrder());
-
Comparator<T> nullsLast(Comparator<T> comparator)
:返回一个比较器,该比较器在比较时将空值排在最后。javaComparator<String> comparator = ComparatorUtils.nullsLast(Comparator.naturalOrder());
-
Comparator<T> chained(Comparator<T>... comparators)
:返回一个组合比较器,按照提供的比较器顺序进行比较。javaComparator<Person> combinedComparator = ComparatorUtils.chained( Comparator.comparing(Person::getLastName), Comparator.comparing(Person::getFirstName) );
-
Comparator<T> reversed(Comparator<T> comparator)
:返回一个比较器,该比较器与提供的比较器具有相反的顺序。javaComparator<String> reversedComparator = ComparatorUtils.reversed(Comparator.naturalOrder());
4.9.3 使用示例
以下示例展示了如何使用 ComparatorUtils
来处理多个比较器并进行排序。
java
import org.apache.commons.collections4.ComparatorUtils;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class ComparatorUtilsExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", null, "Dave");
// 使用 nullsLast 处理空值
names.sort(ComparatorUtils.nullsLast(Comparator.naturalOrder()));
System.out.println("Sorted with nulls last: " + names);
// 组合比较器
List<Person> people = Arrays.asList(
new Person("Alice", "Smith"),
new Person("Bob", "Johnson"),
new Person("Alice", "Johnson")
);
people.sort(ComparatorUtils.chained(
Comparator.comparing(Person::getFirstName),
Comparator.comparing(Person::getLastName)
));
// 输出排序后的结果
System.out.println("Sorted people: " + people);
}
}
class Person {
private String firstName;
private String lastName;
// Constructor, getters, and toString() omitted for brevity
}
4.9.4 使用场景
- 自定义排序:在需要对复杂对象进行多重排序时,使用组合比较器可以简化代码。
- 空值优先级处理:在排序时处理空值时,能够灵活指定它们的位置。
- 集合操作:在进行集合排序时,能够简化比较器的创建和使用。
4.9.5 性能
- 时间复杂度:与排序算法相关,使用组合比较器时,通常保持 O(n log n) 的时间复杂度。
- 空间复杂度:额外的空间复杂度通常较低,主要用于存储比较器。
4.10. FixedSizeList、LazyList、UnmodifiableList
在 Apache Commons Collections4 中,FixedSizeList
、LazyList
和 UnmodifiableList
是用于创建不同特性列表的工具类。每个类都有其特定的用途和特点,下面逐一展开说明。
4.10.1 FixedSizeList
FixedSizeList
是一种固定大小的列表实现,它限制了列表的大小,不允许添加或删除元素。这个特性使得它适用于那些对元素数量有严格控制的场合。
-
创建:
使用
FixedSizeList
,可以通过调用FixedSizeList.fixedSizeList(List<T> list)
方法创建一个固定大小的列表。javaList<String> originalList = new ArrayList<>(Arrays.asList("A", "B", "C")); List<String> fixedSizeList = FixedSizeList.fixedSizeList(originalList);
-
行为:
- 尝试添加元素会抛出
UnsupportedOperationException
。 - 可以修改列表中的现有元素,但不能更改列表的大小。
javafixedSizeList.set(1, "D"); // 修改成功 fixedSizeList.add("E"); // 抛出异常
- 尝试添加元素会抛出
4.10.2 LazyList
LazyList
是一种延迟加载的列表实现,只有在访问元素时才会初始化元素。这个特性非常适合处理大型数据集,特别是在需要延迟加载数据以提高性能的情况下。
-
创建:
使用
LazyList
,可以通过调用LazyList.lazyList(List<T> list, Factory<T> factory)
方法来创建。javaList<String> lazyList = LazyList.lazyList(new ArrayList<>(), () -> "defaultValue");
-
行为:
- 当访问未初始化的元素时,会自动调用提供的工厂方法来初始化该元素。
- 支持修改和删除元素,但只有在元素被实际访问时才会执行初始化。
javaString value = lazyList.get(0); // 触发初始化,返回 "defaultValue" lazyList.set(0, "New Value"); // 修改元素
4.10.3 UnmodifiableList
UnmodifiableList
是一种不可修改的列表实现,它包装了另一个列表,使其不可变。这种实现适用于需要提供只读访问的场合,确保数据不被修改。
-
创建:
可以通过调用
UnmodifiableList.unmodifiableList(List<T> list)
方法创建。javaList<String> originalList = new ArrayList<>(Arrays.asList("A", "B", "C")); List<String> unmodifiableList = UnmodifiableList.unmodifiableList(originalList);
-
行为:
- 所有对列表的修改操作(如
add
、remove
、set
)都会抛出UnsupportedOperationException
。 - 可以安全地在多线程环境中共享,因为列表不会被修改。
javaunmodifiableList.add("D"); // 抛出异常 String value = unmodifiableList.get(0); // 允许访问元素
- 所有对列表的修改操作(如
4.10.4 使用示例
以下示例展示了如何使用 FixedSizeList
、LazyList
和 UnmodifiableList
:
java
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.list.FixedSizeList;
import org.apache.commons.collections4.list.LazyList;
import org.apache.commons.collections4.list.UnmodifiableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListUtilsExample {
public static void main(String[] args) {
// 使用 FixedSizeList
List<String> originalList = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> fixedSizeList = FixedSizeList.fixedSizeList(originalList);
fixedSizeList.set(0, "Z"); // 修改成功
System.out.println("FixedSizeList: " + fixedSizeList);
// fixedSizeList.add("D"); // 抛出异常
// 使用 LazyList
List<String> lazyList = LazyList.lazyList(new ArrayList<>(), () -> "defaultValue");
String value = lazyList.get(0); // 触发初始化
System.out.println("LazyList first element: " + value); // 输出 "defaultValue"
lazyList.set(0, "New Value"); // 修改元素
System.out.println("LazyList first element after modification: " + lazyList.get(0));
// 使用 UnmodifiableList
List<String> unmodifiableList = UnmodifiableList.unmodifiableList(originalList);
// unmodifiableList.add("D"); // 抛出异常
System.out.println("UnmodifiableList: " + unmodifiableList);
}
}
4.10.5 使用场景
- FixedSizeList:适合需要限制大小的场景,例如实现固定大小的缓存。
- LazyList:适用于延迟加载数据的场合,可以减少内存消耗和提升性能。
- UnmodifiableList:适合需要提供只读视图的场景,如防止数据被意外修改。