Java 集合工具类

Java 集合工具类(java.util.Collections)详解

java.util.Collections 是 Java 提供的集合操作工具类,包含大量静态方法,用于操作或返回集合(如排序、查找、同步控制等)。它弥补了集合实现类自身方法的不足,简化了常见的集合操作。本文将详细讲解其核心功能和常用方法,结合代码示例说明用法。

一、Collections 工具类的特点

  1. 静态方法:所有方法均为 static,无需创建实例,直接通过类名调用(Collections.方法名())。
  2. 通用性:适用于 Collection 框架中的各种集合(ListSetMap 等)。
  3. 功能丰富:涵盖排序、查找、替换、同步化、不可修改化等操作。

二、核心功能与常用方法

1. 排序操作(针对 List

Collections 提供了多种排序方法,仅适用于 List(因 SetMap 的排序依赖其实现类自身特性,如 TreeSetTreeMap)。

方法声明功能描述
static <T extends Comparable<? super T>> void sort(List<T> list)List自然顺序排序(元素需实现 Comparable
static <T> void sort(List<T> list, Comparator<? super T> c)自定义比较器排序
static void reverse(List<?> list)反转 List 中元素的顺序
static void shuffle(List<?> list)随机打乱 List 中元素的顺序(洗牌)
static <T> void swap(List<?> list, int i, int j)交换 List 中指定索引 ij 的元素

代码示例:排序操作

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollectionsSortDemo {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(3);
        numbers.add(1);
        numbers.add(2);
        System.out.println("初始列表:" + numbers); // [3, 1, 2]

        // 1. 自然排序(从小到大)
        Collections.sort(numbers);
        System.out.println("自然排序后:" + numbers); // [1, 2, 3]

        // 2. 自定义比较器(从大到小)
        Collections.sort(numbers, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1; // 反转比较顺序
            }
        });
        System.out.println("自定义排序后:" + numbers); // [3, 2, 1]

        // 3. 反转列表
        Collections.reverse(numbers);
        System.out.println("反转后:" + numbers); // [1, 2, 3]

        // 4. 随机打乱(每次结果不同)
        Collections.shuffle(numbers);
        System.out.println("打乱后:" + numbers); // 例如:[2, 3, 1]

        // 5. 交换元素(索引0和2)
        Collections.swap(numbers, 0, 2);
        System.out.println("交换后:" + numbers); // 例如:[1, 3, 2]
    }
}
2. 查找与替换(针对 List

提供在 List 中查找元素、替换元素的方法,部分方法依赖排序(如二分查找)。

方法声明功能描述
static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key)二分查找指定元素的索引(需先排序,未找到返回负数)
static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c)基于比较器的二分查找(需先按该比较器排序)
static <T> int indexOfSubList(List<?> source, List<?> target)查找子列表 targetsource 中首次出现的索引(未找到返回 -1
static <T> int lastIndexOfSubList(List<?> source, List<?> target)查找子列表 targetsource 中最后出现的索引
static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)list 中所有 oldVal 替换为 newVal(返回是否有替换)
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)返回集合中自然顺序最大的元素
static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)返回集合中比较器定义的最大元素
static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)返回集合中自然顺序最小的元素
static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)返回集合中比较器定义的最小元素

代码示例:查找与替换

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsSearchDemo {
    public static void main(String[] args) {
        // 1. 二分查找(需先排序)
        List<Integer> nums = new ArrayList<>();
        nums.add(10);
        nums.add(20);
        nums.add(30);
        nums.add(40);
        Collections.sort(nums); // 先排序(必须!)
        int index = Collections.binarySearch(nums, 30);
        System.out.println("30的索引:" + index); // 2(找到)
        int index2 = Collections.binarySearch(nums, 25);
        System.out.println("25的索引(未找到):" + index2); // -3(负数表示插入点)

        // 2. 查找子列表
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("B");
        list.add("C");
        List<String> subList = new ArrayList<>();
        subList.add("B");
        subList.add("C");
        int first = Collections.indexOfSubList(list, subList);
        int last = Collections.lastIndexOfSubList(list, subList);
        System.out.println("子列表首次出现索引:" + first); // 1
        System.out.println("子列表最后出现索引:" + last); // 3

        // 3. 替换元素
        boolean replaced = Collections.replaceAll(list, "B", "X");
        System.out.println("是否替换成功:" + replaced); // true
        System.out.println("替换后列表:" + list); // [A, X, C, X, C]

        // 4. 查找最大/最小值
        List<Integer> maxMinList = new ArrayList<>();
        maxMinList.add(5);
        maxMinList.add(2);
        maxMinList.add(8);
        int max = Collections.max(maxMinList);
        int min = Collections.min(maxMinList);
        System.out.println("最大值:" + max); // 8
        System.out.println("最小值:" + min); // 2
    }
}
3. 同步控制(返回线程安全集合)

Java 集合框架中的大部分实现类(如 ArrayListHashMap)都是非线程安全的(多线程并发修改可能导致异常)。Collections 提供了将非线程安全集合转换为线程安全集合的方法,内部通过加锁实现同步。

方法声明功能描述
static <T> Collection<T> synchronizedCollection(Collection<T> c)返回线程安全的 Collection
static <T> List<T> synchronizedList(List<T> list)返回线程安全的 List
static <T> Set<T> synchronizedSet(Set<T> s)返回线程安全的 Set
static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)返回线程安全的 SortedSet
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)返回线程安全的 Map
static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)返回线程安全的 SortedMap

代码示例:线程安全集合

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class CollectionsSynchronizedDemo {
    public static void main(String[] args) {
        // 非线程安全的List
        List<String> unsafeList = new ArrayList<>();
        // 转换为线程安全的List
        List<String> safeList = Collections.synchronizedList(unsafeList);

        // 非线程安全的Map
        Map<String, Integer> unsafeMap = new HashMap<>();
        // 转换为线程安全的Map
        Map<String, Integer> safeMap = Collections.synchronizedMap(unsafeMap);

        // 线程安全集合的使用方式与原集合一致
        safeList.add("Java");
        safeMap.put("Score", 90);
        System.out.println("安全List:" + safeList); // [Java]
        System.out.println("安全Map:" + safeMap); // {Score=90}
    }
}

注意

  • 线程安全集合仅保证单个方法的原子性,复合操作(如“检查再更新”)仍需手动加锁。
  • 性能较低,高并发场景推荐使用 java.util.concurrent 包下的并发集合(如 ConcurrentHashMapCopyOnWriteArrayList)。
4. 不可修改集合(只读集合)

通过 Collections 可以创建不可修改的集合(只读),任何修改操作(如 addremoveput)都会抛出 UnsupportedOperationException,用于保护集合数据不被篡改。

方法声明功能描述
static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c)返回不可修改的 Collection
static <T> List<T> unmodifiableList(List<? extends T> list)返回不可修改的 List
static <T> Set<T> unmodifiableSet(Set<? extends T> s)返回不可修改的 Set
static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s)返回不可修改的 SortedSet
static <K,V> Map<K,V> unmodifiableMap(Map<? extends K,? extends V> m)返回不可修改的 Map
static <K,V> SortedMap<K,V> unmodifiableSortedMap(SortedMap<K,? extends V> m)返回不可修改的 SortedMap

代码示例:不可修改集合

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class CollectionsUnmodifiableDemo {
    public static void main(String[] args) {
        // 原始可修改集合
        List<String> mutableList = new ArrayList<>();
        mutableList.add("A");
        mutableList.add("B");

        // 创建不可修改的List(只读)
        List<String> unmodList = Collections.unmodifiableList(mutableList);
        System.out.println("只读List:" + unmodList); // [A, B]

        // 尝试修改只读集合(抛出异常)
        try {
            unmodList.add("C"); // 编译通过,运行时抛异常
        } catch (UnsupportedOperationException e) {
            System.out.println("错误:" + e.getMessage()); // 不支持的操作
        }

        // 原始集合修改,只读集合也会变化(只读集合是原始集合的视图)
        mutableList.add("C");
        System.out.println("原始集合修改后,只读List:" + unmodList); // [A, B, C]

        // 不可修改的Map示例
        Map<String, Integer> mutableMap = new HashMap<>();
        mutableMap.put("One", 1);
        Map<String, Integer> unmodMap = Collections.unmodifiableMap(mutableMap);
        try {
            unmodMap.put("Two", 2); // 抛异常
        } catch (UnsupportedOperationException e) {
            System.out.println("Map修改错误:" + e.getMessage());
        }
    }
}

注意

  • 不可修改集合是原始集合的视图,若原始集合被修改,只读集合也会同步变化。
  • 若需完全独立的只读集合,需先创建副本(如 new ArrayList<>(original)),再转为只读。
5. 空集合(空的不可修改集合)

Collections 提供了预定义的空集合(空列表、空集、空映射),用于避免返回 null(更安全,减少 NullPointerException)。

方法声明功能描述
static <T> List<T> emptyList()返回空的不可修改 List(泛型)
static <T> Set<T> emptySet()返回空的不可修改 Set(泛型)
static <K,V> Map<K,V> emptyMap()返回空的不可修改 Map(泛型)

代码示例:空集合

import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.Collections;

public class CollectionsEmptyDemo {
    public static void main(String[] args) {
        // 获取空集合(不可修改)
        List<String> emptyList = Collections.emptyList();
        Set<Integer> emptySet = Collections.emptySet();
        Map<String, Double> emptyMap = Collections.emptyMap();

        System.out.println("空List大小:" + emptyList.size()); // 0
        System.out.println("空Set是否为空:" + emptySet.isEmpty()); // true

        // 尝试修改空集合(抛异常)
        try {
            emptyList.add("test");
        } catch (UnsupportedOperationException e) {
            System.out.println("空集合修改错误:" + e.getMessage());
        }

        // 实际应用:方法返回空集合而非null
        List<String> result = getData();
        System.out.println("方法返回的集合大小:" + result.size()); // 0(避免NPE)
    }

    // 模拟查询数据,无结果时返回空集合而非null
    public static List<String> getData() {
        // 假设查询无结果
        return Collections.emptyList(); // 比return null更安全
    }
}
6. 其他实用方法
方法声明功能描述
static <T> boolean addAll(Collection<? super T> c, T... elements)向集合 c 中添加多个元素(可变参数)
static int frequency(Collection<?> c, Object o)统计元素 o 在集合 c 中出现的次数
static boolean disjoint(Collection<?> c1, Collection<?> c2)判断两个集合是否无交集(无共同元素)

代码示例:其他方法

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsOtherDemo {
    public static void main(String[] args) {
        // 1. 批量添加元素
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "Java", "Python", "C++", "Java");
        System.out.println("批量添加后:" + list); // [Java, Python, C++, Java]

        // 2. 统计元素出现次数
        int count = Collections.frequency(list, "Java");
        System.out.println("Java出现次数:" + count); // 2

        // 3. 判断集合是否无交集
        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        List<Integer> list2 = new ArrayList<>();
        list2.add(3);
        list2.add(4);
        List<Integer> list3 = new ArrayList<>();
        list3.add(2);
        list3.add(5);

        boolean isDisjoint1 = Collections.disjoint(list1, list2);
        boolean isDisjoint2 = Collections.disjoint(list1, list3);
        System.out.println("list1与list2无交集:" + isDisjoint1); // true(无共同元素)
        System.out.println("list1与list3无交集:" + isDisjoint2); // false(有共同元素2)
    }
}

三、CollectionsArrays 的区别

  • Collections:操作集合对象ListSetMap 等)。
  • Arrays:操作数组(如数组排序 Arrays.sort()、数组转集合 Arrays.asList() 等)。

两者均为工具类,方法均为静态,分别处理集合和数组的常见操作。

四、最佳实践

  1. 避免返回 null:方法返回集合时,若无数据,返回 Collections.emptyList() 等空集合,而非 null,减少 NullPointerException
  2. 线程安全选择:简单线程安全场景可用 synchronizedList() 等,但高并发推荐 java.util.concurrent 包下的集合。
  3. 不可修改保护:当需要传递集合但不允许修改时,使用 unmodifiableList() 等包装,保护数据完整性。
  4. 排序前检查:使用 binarySearch() 前必须确保集合已排序,否则结果不可靠。

总结

Collections 工具类是 Java 集合操作的“瑞士军刀”,提供了排序、查找、同步化、不可修改化等实用功能,极大简化了集合处理代码。掌握其核心方法,能显著提高开发效率,同时保证代码的安全性和可读性。实际开发中,需根据场景灵活选择合适的方法,尤其注意线程安全和不可修改集合的特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值