Collection、Collections和Collectors

57 阅读4分钟

Collection, Collections, 和 Collectors 是 Java 集合框架中三个容易混淆但功能完全不同的概念。它们分别代表了接口、工具类和收集器工具类。 Collection 是一个接口,位于 java.util 包中,定义了单列集合的各种行为规范; Collections 是一个工具类,位于 java.util 包中,提供了许多静态方法来操作或返回集合,以辅助集合的操作。Collectors 是 Java 8 引入的一个收集器工具类,位于 java.util.stream 包中。它提供了用于 Stream.collect() 方法的各种 Collector 实现。

  1. Collection
  • Collection 是一个接口,它是所有集合类的根接口。它定义了集合的基本操作,如添加元素、删除元素、遍历元素等。

  • 实现 Collection 接口的具体类包括 ArrayList, LinkedList, HashSet, TreeSet 等。这些类提供了对集合的不同实现方式,比如基于数组的实现(ArrayList)、链表实现(LinkedList)、哈希表实现(HashSet)和树形结构实现(TreeSet)。

    例:Collection 接口的 ArrayList 类:

import java.util.ArrayList;
import java.util.Collection;

public class CollectionExample {
    public static void main(String[] args) {
        // 创建一个ArrayList实例,它是Collection的一个实现
        Collection<String> collection = new ArrayList<>();
        
        // 添加元素到集合中
        collection.add("Apple");
        collection.add("Banana");
        collection.add("Orange");

        // 遍历并打印集合中的元素
        for (String element : collection) {
            System.out.println(element);
        }

        // 检查集合是否包含特定元素
        boolean hasBanana = collection.contains("Banana");
        System.out.println("Contains Banana: " + hasBanana);

        // 删除集合中的元素
        collection.remove("Banana");

        // 打印删除后的集合大小
        System.out.println("Size after removal: " + collection.size());
    }
}
  1. Collections
  • Collections 是一个工具类,提供了一系列静态方法,帮助我们操作或返回集合。它包含各种实用的方法来处理或操作 Collection 或其子类型的对象,例如排序、混排、同步控制等。

  • 例如,Collections.sort() 方法可以用来对实现了 List 接口的对象进行排序;Collections.synchronizedList() 方法可以返回指定列表支持的同步(线程安全)列表。

  • 这个类不能被实例化,因为它只包含静态方法和静态变量。

    例:

import java.util.*;

public class CollectionsExample {
   public static void main(String[] args) {
       List<String> list = new ArrayList<>();
       list.add("Orange");
       list.add("Apple");
       list.add("Banana");

       // 使用Collections.sort()方法对列表进行排序
       Collections.sort(list);
       System.out.println("Sorted list: " + list);

       // 使用Collections.shuffle()方法随机排列列表元素
       Collections.shuffle(list);
       System.out.println("Shuffled list: " + list);

       // 使用Collections.synchronizedList()方法创建线程安全的列表
       List<String> syncList = Collections.synchronizedList(new ArrayList<>());
       syncList.add("ThreadSafeItem");
       System.out.println("Synchronized list content: " + syncList);

       // 使用Collections.unmodifiableList()方法创建只读列表
       List<String> unmodifiableList = Collections.unmodifiableList(list);
       // 下面这行代码会抛出UnsupportedOperationException异常,因为unmodifiableList是只读的
       // unmodifiableList.add("New Item");
   }
}

Collections的常用方法

-   **`Collections.singletonList(T item)`** : 创建一个只包含指定元素的、不可变的 `List`-   **`Collections.emptyList()`** : 返回一个空的、不可变的 `List`

3. Collectors: - Collectors 类是 Java 8 引入的 java.util.stream.Collectors 工具类,它提供了各种用于 Stream.collect() 方法的收集器(Collector),这些收集器允许你对流中的元素进行累积、分组、分区等操作。通过 Collectors 提供的方法,你可以方便地将流转换成不同的集合类型,或者执行复杂的聚合操作。 特点:

  • 灵活性Collectors 提供了非常灵活的方式来处理流数据,无论是简单的收集到集合,还是复杂的分组、分区操作。
  • 高效性:使用 Collectors 可以有效地利用流式处理的优势,尤其是对于大数据集时,能够显著提升性能。
  • 易用性:通过静态导入 Collectors 的方法,可以简化代码,使其更加简洁易读。

以下是 Collectors 类中一些常用的方法:

基本收集

  • toList():将流中的元素收集到一个 List 中。

     List<String> list = stream.collect(Collectors.toList());
    
  • toSet():将流中的元素收集到一个 Set 中,自动去除重复项。

 Set<String> set = stream.collect(Collectors.toSet());
  • toCollection(Supplier<Collection> collectionFactory):使用指定的集合工厂函数创建集合,并将流中的元素收集到这个集合中。
 Collection<String> collection = stream.collect(Collectors.toCollection(ArrayList::new));
 
  • toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper):将流中的元素收集到一个 Map 中,需要提供键值映射的函数。
  Map<Integer, String> map = stream.collect(Collectors.toMap(Person::getId, Person::getName));

聚合操作

  • joining() / joining(CharSequence delimiter) / joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix):连接字符串流中的所有元素。可以指定分隔符,前缀和后缀。
 String joined = stream.collect(Collectors.joining(","));
  • counting():返回流中元素数量的总数。
Long count = stream.collect(Collectors.counting());

分组与分区

  • groupingBy(Function<? super T,? extends K> classifier):根据提供的分类函数对流中的元素进行分组,返回一个 Map<K, List<T>>
  Map<Integer, List<Person>> groupedByAge = people.stream().collect(Collectors.groupingBy(Person::getAge));
  • partitioningBy(Predicate<? super T> predicate):根据提供的谓词对流中的元素进行分区(true/false),返回一个 Map<Boolean, List<T>>
  Map<Boolean, List<Person>> partitioned = people.stream().collect(Collectors.partitioningBy(person -> person.getAge() > 18));

组合使用

  • mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream)

    在收集之前对每个输入元素应用映射函数。

     List<String> names = people.stream().collect(Collectors.mapping(Person::getName, Collectors.toList()));
    
  • collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher):首先是收集,然后是对收集结果的转换(包装另一个收集器,对其结果应用一个完成器函数)。

   Set<String> distinctNames = people.stream().collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet));
        // 找到年龄最大的人的名字
        Optional<String> oldestPersonName = people.stream()
            .collect(Collectors.collectingAndThen(
                Collectors.maxBy(Comparator.comparing(Person::getAge)), // 下游收集器:找到年龄最大的 Person
                maxPerson -> maxPerson.map(Person::getName) // 完成器函数:将 Optional<Person> 转换为 Optional<String>
            ));