Java中的聚合操作

在 Java 编程领域中,数据处理是一项常见任务,通常涉及操作对象集合。在 Java 8 发布之前,对集合执行操作需要使用循环或外部库编写冗长且容易出错的代码。然而,随着 Stream API 和聚合操作的引入,Java 8 彻底改变了数据的处理方式,使其更加简洁、可读和高效。

聚合操作也称为流操作,提供了一种声明式和函数式的方法来处理 Java 中的数据。它们使开发人员能够将复杂的数据操作任务表达为一系列链式操作,从而实现更具表现力和可读性的代码。聚合操作由两个主要组件组成:流和操作。

流是可以并行或顺序处理的元素序列。它们提供了对集合和数组的更高级别的抽象,允许对大型数据集进行高效和并行处理。流可以从各种来源创建,例如集合、数组或 I/O 通道。

要创建流,您可以对集合调用stream()或parallelStream()方法,或对数组使用Stream.of()方法。例如:

List<String> names= Arrays.asList( "约翰" ,  "简" ,  "爱丽丝" ,  "鲍勃" );  
Stream<String> stream=names.stream();  

创建流后,您可以对其执行各种操作以转换、过滤或聚合数据。操作可分为两类:中间操作和终端操作。
中间操作是将一个流转换为另一个流的操作。它们是惰性的,这意味着它们在调用终端操作之前不会执行。一些常见的中间操作包括filter()、map()、distinct()、sorted()和limit()。例如:

List<Integer> Numbers= Arrays.asList( 1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7 ,  8 ,  9 ,  10 );  
List<Integer> EvenSquares = Numbers.stream()  
                                   .filter(n -> n %  2  ==  0 )  
                                   .map(n -> n * n)  
                                   .collect(Collectors.toList());  


在上面的代码片段中,首先过滤数字流以仅保留偶数,然后使用 map() 操作对每个数字进行平方。最后,结果被收集到一个新列表中。

终端操作是产生结果或副作用的操作。它们触发流管道的执行并消耗流。终端操作的示例包括forEach()、collect()、count()、max()、min() 和reduce()。例如:

List<String> fruits = Arrays.asList("apple", "banana", "orange", "mango");  
long count = fruits.stream()  
                   .filter(fruit -> fruit.startsWith(
"a"))  
                   .count();  
System.out.println(
"Count: " + count);  

在上面的代码片段中,count() 终端操作用于计算数据流中以字母 "a "开头的水果数量。

聚合操作旨在与 lambda 表达式无缝配合,使开发人员能够编写简洁而富有表现力的代码。通过 lambda 表达式,可以定义内联函数,从而更容易将行为作为参数传递给流操作。除内置操作外,Java 8 还引入了收集器接口,允许将元素自定义聚合到集合或地图等容器中。收集器提供了一种强大的方法,可将流中的元素聚合到可变结果容器中。

Java 8 中的聚合操作简化并精简了数据处理,为操作集合提供了功能更强、表现力更强的方法。它们使编写简洁、易读的代码变得更加容易,减少了对传统命令式循环和外部库的需求。通过利用流和操作,开发人员可以利用并行处理功能,从而在多核系统上获得更好的性能。

import java.util.Arrays;  
import java.util.List;  
import java.util.stream.Collectors;  
public class AggregateOperationsExample {  
    public static void main(String[] args) {  
        // Example 1: Filtering and Mapping  
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
        List<Integer> evenSquares = numbers.stream()  
                .filter(n -> n % 2 == 0)  
                .map(n -> n * n)  
                .collect(Collectors.toList());  
        System.out.println(
"Even Squares: " + evenSquares);  
       
// Output: Even Squares: [4, 16, 36, 64, 100]  
       
// Example 2: Counting  
        List<String> fruits = Arrays.asList(
"apple", "banana", "orange", "mango");  
        long count = fruits.stream()  
                .filter(fruit -> fruit.startsWith(
"a"))  
                .count();  
        System.out.println(
"Count: " + count);  
       
// Output: Count: 1  
    }  
}  

以下是一些常见的聚合操作总结:

forEach:
对流中的每个元素执行指定的操作。

List<String> words = Arrays.asList("apple", "orange", "banana");
words.stream().forEach(System.out::println);

filter:
返回由满足给定谓词的元素组成的流。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream().filter(n -> n % 2 == 0).forEach(System.out::println);

map:
使用提供的函数转换每个元素。

List<String> words = Arrays.asList("apple", "orange", "banana");
words.stream().map(String::toUpperCase).forEach(System.out::println);

reduce:
使用关联的累积函数对流的元素执行归约操作,并返回一个Optional。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
System.out.println("Sum: " + sum.orElse(0));

collect:
对流的元素执行可变归约,将其收集到不同形式,例如集合(List、Set、Map)中。

List<String> words = Arrays.asList("apple", "orange", "banana");
List<String> uppercasedWords = words.stream().map(String::toUpperCase).collect(Collectors.toList());

count:
返回流中的元素数量。

List<String> words = Arrays.asList("apple", "orange", "banana");
long count = words.stream().count();
System.out.println(
"Count: " + count);


总之
Java 8 中的聚合操作改变了 Java 编程语言处理数据的方式。通过引入流和一系列功能强大的操作,Java 8 使开发人员能够编写更优雅、更高效的代码来处理集合。无论是过滤、映射还是归约reduce数据,聚合操作都提供了一种声明性和功能性的方法,从而简化了复杂的数据操作任务。因此,请利用聚合操作的强大功能,在 Java 8 中简化您的数据处理。