在 Java 编程中,集合(Collections)是处理数据的核心工具之一。为了简化集合操作并提高代码的可读性和可维护性,JDK 提供了一个强大的工具类:java.util.Collections
。这个类包含了一系列静态方法,用于对集合进行各种操作,如排序、查找、同步控制、创建不可变集合等。
1 引入 Collections 类
Collections
类位于 java.util
包中,因此在使用之前需要导入:
import java.util.Collections;
2 排序操作
Collections
类提供了多种排序方法,可以对集合进行反转、洗牌、自然排序和自定义排序等操作。
reverse(List list)
:反转集合中元素的顺序。shuffle(List list)
:随机打乱集合中元素的顺序。sort(List list)
:对集合进行自然升序排序。sort(List list, Comparator c)
:根据自定义比较器对集合进行排序。swap(List list, int i, int j)
:交换集合中指定位置的两个元素。
示例代码:
List<String> list = new ArrayList<>();
list.add("沉默王二");
list.add("沉默王三");
list.add("沉默王四");
list.add("沉默王五");
list.add("沉默王六");
System.out.println("原始顺序:" + list);
// 反转
Collections.reverse(list);
System.out.println("反转后:" + list);
// 洗牌
Collections.shuffle(list);
System.out.println("洗牌后:" + list);
// 自然升序
Collections.sort(list);
System.out.println("自然升序后:" + list);
// 交换
Collections.swap(list, 2, 4);
System.out.println("交换后:" + list);
输出结果:
原始顺序:[沉默王二, 沉默王三, 沉默王四, 沉默王五, 沉默王六]
反转后:[沉默王六, 沉默王五, 沉默王四, 沉默王三, 沉默王二]
洗牌后:[沉默王五, 沉默王二, 沉默王六, 沉默王三, 沉默王四]
自然升序后:[沉默王三, 沉默王二, 沉默王五, 沉默王六, 沉默王四]
交换后:[沉默王三, 沉默王二, 沉默王四, 沉默王六, 沉默王五]
3 查找操作
Collections
类提供了多种查找方法,可以用于查找集合中的最大值、最小值、元素出现的次数等。
binarySearch(List list, Object key)
:二分查找法,前提是集合已经排序。max(Collection coll)
:返回集合中的最大元素。max(Collection coll, Comparator comp)
:根据自定义比较器返回集合中的最大元素。min(Collection coll)
:返回集合中的最小元素。min(Collection coll, Comparator comp)
:根据自定义比较器返回集合中的最小元素。fill(List list, Object obj)
:使用指定对象填充集合。frequency(Collection c, Object o)
:返回指定对象在集合中出现的次数。
示例代码:
System.out.println("最大元素:" + Collections.max(list));
System.out.println("最小元素:" + Collections.min(list));
System.out.println("出现的次数:" + Collections.frequency(list, "沉默王二"));
// 没有排序直接调用二分查找,结果是不确定的
System.out.println("排序前的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));
Collections.sort(list);
// 排序后,查找结果和预期一致
System.out.println("排序后的二分查找结果:" + Collections.binarySearch(list, "沉默王二"));
Collections.fill(list, "沉默王八");
System.out.println("填充后的结果:" + list);
输出结果:
最大元素:沉默王四
最小元素:沉默王三
出现的次数:1
排序前的二分查找结果:0
排序后的二分查找结果:1
填充后的结果:[沉默王八, 沉默王八, 沉默王八, 沉默王八, 沉默王八]
4 同步控制
在多线程环境下,集合操作可能会引发线程安全问题。Collections
类提供了 synchronizedXxx
方法,用于返回一个同步的集合对象,从而避免线程安全问题。
示例代码:
SynchronizedList synchronizedList = Collections.synchronizedList(list);
SynchronizedList
的源码实现非常简单,只是在方法内部使用 synchronized
关键字加了一层锁。
static class SynchronizedList<E>
extends SynchronizedCollection<E>
implements List<E> {
private static final long serialVersionUID = -7754090372962971524L;
final List<E> list;
SynchronizedList(List<E> list) {
super(list); // 调用父类 SynchronizedCollection 的构造方法,传入 list
this.list = list; // 初始化成员变量 list
}
// 获取指定索引处的元素
public E get(int index) {
synchronized (mutex) {return list.get(index);} // 加锁,调用 list 的 get 方法获取元素
}
// 在指定索引处插入指定元素
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);} // 加锁,调用 list 的 add 方法插入元素
}
// 移除指定索引处的元素
public E remove(int index) {
synchronized (mutex) {return list.remove(index);} // 加锁,调用 list 的 remove 方法移除元素
}
}
那这样的话,其实效率和那些直接在方法上加 synchronized
关键字的 Vector
、Hashtable
差不多(JDK 1.0 时期就有了),而这些集合类基本上已经废弃了,几乎不怎么用。
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
// 获取指定索引处的元素
public synchronized E get(int index) {
if (index >= elementCount) // 如果索引超出了列表的大小,则抛出数组下标越界异常
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index); // 返回指定索引处的元素
}
// 移除指定索引处的元素
public synchronized E remove(int index) {
modCount++; // 修改计数器,标识列表已被修改
if (index >= elementCount) // 如果索引超出了列表的大小,则抛出数组下标越界异常
throw new ArrayIndexOutOfBoundsException(index);
E oldValue = elementData(index); // 获取指定索引处的元素
int numMoved = elementCount - index - 1; // 计算需要移动的元素个数
if (numMoved > 0) // 如果需要移动元素
System.arraycopy(elementData, index+1, elementData, index,
numMoved); // 将数组中的元素向左移动一位
elementData[--elementCount] = null; // 将最后一个元素设置为 null,等待垃圾回收
return oldValue; // 返回被移除的元素
}
}
正确的做法是使用并发包下的 CopyOnWriteArrayList
、ConcurrentHashMap
。
5 不可变集合
Collections
类提供了多种方法来创建不可变集合,这些集合一旦创建,就无法进行修改操作。
emptyXxx()
:创建一个空的不可变集合。singletonXxx()
:创建一个只包含一个元素的不可变集合。unmodifiableXxx()
:为指定集合创建一个不可变视图。
示例代码:
List emptyList = Collections.emptyList();
emptyList.add("非空"); // 抛出 UnsupportedOperationException
System.out.println(emptyList);
输出结果:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.itwanger.s64.Demo.main(Demo.java:61)
6 其他操作
Collections
类还提供了一些其他常用的方法:
addAll(Collection<? super T> c, T... elements)
:将多个元素添加到集合中。disjoint(Collection<?> c1, Collection<?> c2)
:判断两个集合是否没有交集。
示例代码:
List<String> allList = new ArrayList<>();
Collections.addAll(allList, "沉默王九", "沉默王十", "沉默王二");
System.out.println("addAll 后:" + allList);
System.out.println("是否没有交集:" + (Collections.disjoint(list, allList) ? "是" : "否"));
输出结果:
addAll 后:[沉默王九, 沉默王十, 沉默王二]
是否没有交集:否
7 CollectionUtils:Spring 和 Apache 的集合工具类
除了 JDK 提供的 Collections
工具类,Spring 和 Apache 也提供了各自的集合工具类,如 org.springframework.util.CollectionUtils
和 org.apache.commons.collections.CollectionUtils
。
Apache 的 CollectionUtils
提供了更多实用的方法,如集合判空、集合操作(交集、并集、差集等)。
Maven 坐标:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
示例代码:
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(1);
list.add(3);
List<Integer> list2 = new ArrayList<>();
list2.add(2);
list2.add(4);
// 获取并集
Collection<Integer> unionList = CollectionUtils.union(list, list2);
System.out.println(unionList);
// 获取交集
Collection<Integer> intersectionList = CollectionUtils.intersection(list, list2);
System.out.println(intersectionList);
// 获取交集的补集
Collection<Integer> disjunctionList = CollectionUtils.disjunction(list, list2);
System.out.println(disjunctionList);
// 获取差集
Collection<Integer> subtractList = CollectionUtils.subtract(list, list2);
System.out.println(subtractList);
输出结果:
[1, 2, 3, 4]
[2]
[1, 3, 4]
[1, 3]
8 小结
Collections
工具类作为集合框架的大管家,提供了丰富的静态方法,帮助开发者简化集合操作,提高代码的可读性和可维护性。掌握这些方法,可以显著提升编程效率,减少出错的可能性。
虽然 Collections
工具类非常强大,但更重要的是理解其背后的设计思想和实现原理。通过阅读源码,学习 JDK 设计者的编程技巧,可以进一步提升自己的编码水平。
在实际工作中,合理利用 Collections
工具类和第三方工具类(如 Apache 的 CollectionUtils
),可以大大简化集合操作,提高代码质量。
9 思维导图
10 参考链接
Java Collections:专为集合框架而生的工具类