1. 概述
简单来说,Apache Commons Collections 的 CollectionUtils
提供了一系列实用方法,用于处理常见的集合操作。这些方法覆盖了广泛的使用场景,能有效减少我们编写样板代码的工作量。该库主要面向较旧的 JVM 版本,因为 Java 8 的 Stream API 已经提供了类似功能。
2. Maven 依赖
要使用 CollectionUtils
,我们需要添加以下 Maven 依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
最新版本可以在 这里 找到。
3. 环境准备
我们先定义两个基础类 Customer
和 Address
:
public class Customer {
private Integer id;
private String name;
private Address address;
// 标准 getter 和 setter
}
public class Address {
private String locality;
private String city;
// 标准 getter 和 setter
}
为了测试后续实现,我们准备以下 Customer
对象和 List
实例:
Customer customer1 = new Customer(1, "Daniel", "locality1", "city1");
Customer customer2 = new Customer(2, "Fredrik", "locality2", "city2");
Customer customer3 = new Customer(3, "Kyle", "locality3", "city3");
Customer customer4 = new Customer(4, "Bob", "locality4", "city4");
Customer customer5 = new Customer(5, "Cat", "locality5", "city5");
Customer customer6 = new Customer(6, "John", "locality6", "city6");
List<Customer> list1 = Arrays.asList(customer1, customer2, customer3);
List<Customer> list2 = Arrays.asList(customer4, customer5, customer6);
List<Customer> list3 = Arrays.asList(customer1, customer2);
List<Customer> linkedList1 = new LinkedList<>(list1);
4. CollectionUtils 核心方法
下面我们介绍 Apache Commons CollectionUtils
中最常用的几个方法。
4.1 添加非空元素
使用 addIgnoreNull
方法可以仅向集合中添加非空元素。该方法接收两个参数:
- 目标集合
- 待添加元素
@Test
public void givenList_whenAddIgnoreNull_thenNoNullAdded() {
CollectionUtils.addIgnoreNull(list1, null);
assertFalse(list1.contains(null));
}
✅ 注意:null
值不会被添加到列表中。
4.2 合并有序列表
使用 collate
方法可以合并两个已排序的列表。该方法返回一个新的有序列表:
@Test
public void givenTwoSortedLists_whenCollated_thenSorted() {
List<Customer> sortedList = CollectionUtils.collate(list1, list2);
assertEquals(6, sortedList.size());
assertTrue(sortedList.get(0).getName().equals("Bob"));
assertTrue(sortedList.get(2).getName().equals("Daniel"));
}
4.3 对象转换
通过 transform
方法可以将 A 类对象列表转换为 B 类对象列表。需要提供:
- 原始对象列表
- 转换器(Transformer)
@Test
public void givenListOfCustomers_whenTransformed_thenListOfAddress() {
Collection<Address> addressCol = CollectionUtils.collect(list1,
new Transformer<Customer, Address>() {
public Address transform(Customer customer) {
return customer.getAddress();
}
});
List<Address> addressList = new ArrayList<>(addressCol);
assertTrue(addressList.size() == 3);
assertTrue(addressList.get(0).getLocality().equals("locality1"));
}
4.4 对象过滤
使用 filter
方法可以移除列表中不满足条件的元素。参数包括:
- 目标列表
- 断言(Predicate)
⚠️ 注意:filterInverse
方法作用相反,会移除满足条件的元素。两个方法都返回 boolean
表示列表是否被修改:
@Test
public void givenCustomerList_WhenFiltered_thenCorrectSize() {
boolean isModified = CollectionUtils.filter(linkedList1,
new Predicate<Customer>() {
public boolean evaluate(Customer customer) {
return Arrays.asList("Daniel","Kyle").contains(customer.getName());
}
});
assertTrue(linkedListList1.size() == 2);
}
如果需要返回过滤后的新列表而非布尔值,可以使用 select
和 selectRejected
。
4.5 非空检查
isNotEmpty
方法是检查集合是否至少包含一个元素的利器。传统写法:
boolean isNotEmpty = (list != null && list.size() > 0);
使用 CollectionUtils.isNotEmpty
更简洁:
@Test
public void givenNonEmptyList_whenCheckedIsNotEmpty_thenTrue() {
assertTrue(CollectionUtils.isNotEmpty(list1));
}
isEmpty
方法作用相反,检查集合是否为 null
或空:
List<Customer> emptyList = new ArrayList<>();
List<Customer> nullList = null;
assertTrue(CollectionUtils.isEmpty(nullList));
assertTrue(CollectionUtils.isEmpty(emptyList));
4.6 包含关系检查
使用 isSubCollection
可以检查一个集合是否是另一个集合的子集:
@Test
public void givenCustomerListAndASubcollection_whenChecked_thenTrue() {
assertTrue(CollectionUtils.isSubCollection(list3, list1));
}
子集定义:集合 A 中每个元素的出现次数 ≤ 集合 B 中的出现次数。
4.7 集合交集
使用 intersection
方法获取两个集合的交集:
@Test
public void givenTwoLists_whenIntersected_thenCheckSize() {
Collection<Customer> intersection = CollectionUtils.intersection(list1, list3);
assertTrue(intersection.size() == 2);
}
结果中元素的出现次数 = 两个输入集合中该元素出现次数的最小值。
4.8 集合差集
使用 subtract
方法计算差集(存在于第一个集合但不存在于第二个集合的元素):
@Test
public void givenTwoLists_whenSubtracted_thenCheckElementNotPresentInA() {
Collection<Customer> result = CollectionUtils.subtract(list1, list3);
assertFalse(result.contains(customer1));
}
结果中元素的出现次数 = 第一个集合中的出现次数 - 第二个集合中的出现次数。
4.9 集合并集
使用 union
方法计算两个集合的并集:
@Test
public void givenTwoLists_whenUnioned_thenCheckElementPresentInResult() {
Collection<Customer> union = CollectionUtils.union(list1, list2);
assertTrue(union.contains(customer1));
assertTrue(union.contains(customer4));
}
结果中元素的出现次数 = 两个输入集合中该元素出现次数的最大值。
5. 总结
到这里就结束了。我们介绍了 CollectionUtils
中最常用的几个方法,这些方法在 Java 项目中处理集合时能有效减少样板代码。完整代码可以在 GitHub 上查看。