跳转至

Java 中 Collectors 导入与使用全解析

简介

在 Java 编程中,Collectorsjava.util.stream 包下的一个实用类,它提供了一系列的静态方法,用于在流操作中进行各种规约操作,比如将流中的元素收集到集合中、进行分组、分区、计算统计信息等。本文将详细介绍 Collectors 的基础概念、使用方法、常见实践以及最佳实践,帮助读者深入理解并高效使用 Collectors

目录

  1. 基础概念
  2. 使用方法
  3. 常见实践
  4. 最佳实践
  5. 小结
  6. 参考资料

1. 基础概念

Collectors 类是 Java 8 引入的一个工具类,它实现了各种有用的归约操作,如将元素累积到集合中,根据各种标准对元素进行汇总等。在流处理中,Collectors 通常与 Streamcollect() 方法一起使用,将流中的元素进行收集和转换。

collect() 方法是 Stream 接口的一个终端操作,它接受一个 Collector 作为参数,Collector 定义了如何将流中的元素收集到目标容器中。Collectors 类提供了许多预定义的 Collector 实现,方便我们进行常见的收集操作。

2. 使用方法

要使用 Collectors,首先需要导入 java.util.stream.Collectors 类:

import java.util.stream.Collectors;

以下是一个简单的示例,将一个 List 中的元素收集到另一个 List 中:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CollectorsExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> collectedNumbers = numbers.stream()
                .collect(Collectors.toList());
        System.out.println(collectedNumbers);
    }
}

在这个示例中,我们使用 Collectors.toList() 方法创建了一个 Collector,它将流中的元素收集到一个 List 中。然后调用 Streamcollect() 方法执行收集操作。

3. 常见实践

3.1 收集到不同的集合

除了 toList()Collectors 还提供了 toSet()toMap() 方法,分别用于将流中的元素收集到 SetMap 中。

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class CollectToDifferentCollections {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);

        // 收集到 Set
        Set<Integer> set = numbers.stream()
                .collect(Collectors.toSet());
        System.out.println("Set: " + set);

        // 收集到 Map
        Map<Integer, Integer> map = numbers.stream()
                .collect(Collectors.toMap(num -> num, num -> num * num));
        System.out.println("Map: " + map);
    }
}

3.2 分组

Collectors.groupingBy() 方法可以根据指定的分类函数对元素进行分组。

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

public class GroupingExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 20),
                new Person("Bob", 25),
                new Person("Charlie", 20)
        );

        Map<Integer, List<Person>> groupedByAge = people.stream()
                .collect(Collectors.groupingBy(Person::getAge));
        System.out.println(groupedByAge);
    }
}

3.3 分区

Collectors.partitioningBy() 方法可以根据布尔条件对元素进行分区。

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class PartitioningExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Map<Boolean, List<Integer>> partitioned = numbers.stream()
                .collect(Collectors.partitioningBy(num -> num % 2 == 0));
        System.out.println(partitioned);
    }
}

3.4 统计信息

Collectors 还提供了一些方法用于计算统计信息,如 counting()summingInt()averagingInt() 等。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StatisticsExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        long count = numbers.stream()
                .collect(Collectors.counting());
        System.out.println("Count: " + count);

        int sum = numbers.stream()
                .collect(Collectors.summingInt(num -> num));
        System.out.println("Sum: " + sum);

        double average = numbers.stream()
                .collect(Collectors.averagingInt(num -> num));
        System.out.println("Average: " + average);
    }
}

4. 最佳实践

4.1 使用不可变集合

如果需要一个不可变的集合,可以使用 Collectors.toUnmodifiableList()Collectors.toUnmodifiableSet()Collectors.toUnmodifiableMap() 方法。

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class ImmutableCollectionExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Integer> immutableList = numbers.stream()
                .collect(Collectors.toUnmodifiableList());
        // 尝试修改会抛出 UnsupportedOperationException
        // immutableList.add(6); 
    }
}

4.2 组合收集器

可以将多个收集器组合使用,以实现更复杂的收集操作。例如,在分组后对每个组中的元素进行进一步的收集。

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

public class CombiningCollectorsExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 20),
                new Person("Bob", 25),
                new Person("Charlie", 20)
        );

        Map<Integer, Long> countByAge = people.stream()
                .collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
        System.out.println(countByAge);
    }
}

5. 小结

Collectors 类是 Java 流处理中非常强大的工具,它提供了丰富的静态方法,用于实现各种归约操作。通过使用 Collectors,我们可以方便地将流中的元素收集到不同的集合中,进行分组、分区和统计等操作。在使用时,建议使用不可变集合和组合收集器,以提高代码的安全性和灵活性。

6. 参考资料

  • 《Effective Java》(第 3 版)
  • 《Java 8 in Action》