跳转到内容

Java Stream收集

来自代码酷

Java Stream收集[编辑 | 编辑源代码]

Java Stream收集(Collectors)是Java Stream API中的一个核心概念,它允许开发者通过`Collectors`工具类将流中的元素聚合为集合、字符串、统计结果或其他数据结构。收集操作通常通过`Stream.collect()`方法实现,是流处理的终端操作之一。

介绍[编辑 | 编辑源代码]

在Java 8引入的Stream API中,流(Stream)代表一系列元素,支持顺序或并行操作。而收集(Collecting)是流处理的最后一步,将流中的元素转换为具体的数据结构(如`List`、`Set`、`Map`)或计算聚合结果(如求和、平均值)。`Collectors`类提供了丰富的静态工厂方法,用于实现常见的收集操作。

基本收集操作[编辑 | 编辑源代码]

以下是一些基本的收集操作示例:

收集为List[编辑 | 编辑源代码]

将流中的元素收集到`List`中:

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

public class CollectExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "C++");
        List<String> list = stream.collect(Collectors.toList());
        System.out.println(list); // 输出: [Java, Python, C++]
    }
}

收集为Set[编辑 | 编辑源代码]

将流中的元素收集到`Set`中(自动去重):

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CollectExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "Java");
        Set<String> set = stream.collect(Collectors.toSet());
        System.out.println(set); // 输出: [Java, Python](顺序可能不同)
    }
}

收集为Map[编辑 | 编辑源代码]

将流中的元素转换为键值对:

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CollectExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "C++");
        Map<String, Integer> map = stream.collect(
            Collectors.toMap(s -> s, String::length)
        );
        System.out.println(map); // 输出: {Java=4, Python=6, C++=3}
    }
}

高级收集操作[编辑 | 编辑源代码]

`Collectors`还支持更复杂的聚合操作,如分组、分区和统计。

分组(Grouping By)[编辑 | 编辑源代码]

按某个条件对流中的元素分组:

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

public class GroupingExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "C++", "JavaScript");
        Map<Integer, List<String>> groupedByLength = stream.collect(
            Collectors.groupingBy(String::length)
        );
        System.out.println(groupedByLength); 
        // 输出: {2=[C++], 4=[Java], 6=[Python], 10=[JavaScript]}
    }
}

分区(Partitioning By)[编辑 | 编辑源代码]

将流中的元素分为`true`和`false`两组:

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class PartitioningExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "C++", "JavaScript");
        Map<Boolean, List<String>> partitioned = stream.collect(
            Collectors.partitioningBy(s -> s.length() > 4)
        );
        System.out.println(partitioned); 
        // 输出: {false=[Java, C++], true=[Python, JavaScript]}
    }
}

统计(Summarizing)[编辑 | 编辑源代码]

计算数值流的统计信息(总和、平均值、最大值等):

import java.util.IntSummaryStatistics;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StatisticsExample {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        IntSummaryStatistics stats = stream.collect(
            Collectors.summarizingInt(Integer::intValue)
        );
        System.out.println("总和: " + stats.getSum());       // 输出: 15
        System.out.println("平均值: " + stats.getAverage()); // 输出: 3.0
        System.out.println("最大值: " + stats.getMax());     // 输出: 5
    }
}

自定义收集器[编辑 | 编辑源代码]

如果内置的`Collectors`不满足需求,可以通过`Collector.of()`自定义收集器。以下是一个拼接字符串的自定义收集器示例:

import java.util.stream.Collector;
import java.util.stream.Stream;

public class CustomCollectorExample {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("Java", "Python", "C++");
        String result = stream.collect(
            Collector.of(
                StringBuilder::new,
                StringBuilder::append,
                StringBuilder::append,
                StringBuilder::toString
            )
        );
        System.out.println(result); // 输出: JavaPythonC++
    }
}

实际应用案例[编辑 | 编辑源代码]

假设有一个订单列表,需要按用户分组并计算每个用户的订单总金额:

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

class Order {
    String user;
    double amount;

    Order(String user, double amount) {
        this.user = user;
        this.amount = amount;
    }
}

public class OrderAnalysis {
    public static void main(String[] args) {
        List<Order> orders = List.of(
            new Order("Alice", 100.0),
            new Order("Bob", 200.0),
            new Order("Alice", 150.0)
        );

        Map<String, Double> totalByUser = orders.stream()
            .collect(Collectors.groupingBy(
                o -> o.user,
                Collectors.summingDouble(o -> o.amount)
            ));

        System.out.println(totalByUser); // 输出: {Alice=250.0, Bob=200.0}
    }
}

性能注意事项[编辑 | 编辑源代码]

  • 并行流(`parallelStream()`)可以加速收集操作,但需确保收集器是线程安全的。
  • 对于大数据集,避免频繁调用`collect()`,尽量合并操作。

总结[编辑 | 编辑源代码]

Java Stream收集是流处理的核心功能之一,通过`Collectors`类可以实现从简单聚合到复杂分组的操作。掌握这些技巧能显著提升代码的简洁性和可读性。

graph LR A[Stream] --> B[Filter/Map等中间操作] B --> C[Collect终端操作] C --> D[List/Set/Map等结果]

通过本文的学习,你应该能够熟练使用`Collectors`完成各种流收集任务。