什么是 Stream 流

定义:Stream 是 Java 8 中引入的一个新的抽象层,它可以让你以一种声明式的方式处理集合(Collection)数据。简单来说,它就像是一条流水线,数据(集合中的元素)在这条流水线上流动,并且可以在流动的过程中进行各种操作,如过滤、映射、排序等。特点:

惰性求值:Stream 流操作分为中间操作和终端操作。中间操作只是定义了对数据的处理方式,并不会立即执行,只有当终端操作被调用时,整个 Stream 流的操作才会真正执行。例如,你定义了一个过滤操作和一个计数操作,只有当你执行计数操作(终端操作)时,过滤操作(中间操作)才会被执行。不可变数据:Stream 流本身不会修改数据源。它返回的是一个新的 Stream 或者一个计算结果,而原始的数据集合不会被改变。函数式编程风格:Stream API 大量使用了 Lambda 表达式,这使得代码更加简洁和易于理解。你可以将操作看作是对数据集合的一系列函数调用。Stream 流常用的方法

中间操作方法

filter(Predicate predicate):

功能:用于过滤 Stream 中的元素。它接受一个 Predicate(断言)作为参数,这个断言是一个返回布尔值的函数。只有当断言返回 true 时,元素才会被保留在 Stream 中。示例:假设有一个包含整数的 List,要过滤出所有偶数。

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

Stream evenNumbersStream = numbers.stream().filter(n -> n % 2 == 0);

// 此时还没有真正执行过滤操作,因为filter是中间操作

evenNumbersStream.forEach(System.out::println);

// 当执行终端操作forEach时,filter操作才会被执行,输出2, 4, 6

}

}

map(Function mapper):

功能:将 Stream 中的每个元素通过一个 Function(函数)进行转换,返回一个包含转换后元素的新 Stream。示例:假设有一个包含字符串的 List,要将每个字符串转换为其长度。

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List words = Arrays.asList("apple", "banana", "cherry");

Stream lengthsStream = words.stream().map(String::length);

lengthsStream.forEach(System.out::println);

// 输出3, 6, 6,因为"apple"长度为3,"banana"长度为6,"cherry"长度为6

}

}

flatMap(Function> mapper):

功能:和 map 类似,但它可以将一个元素转换为一个 Stream,然后将这些子 Stream 中的元素合并成一个新的 Stream。通常用于处理嵌套的数据结构,如将二维数组或包含集合的集合转换为一维的 Stream。示例:假设有一个包含多个字符串数组的 List,要将所有字符串合并到一个 Stream 中。

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List stringArrays = Arrays.asList(new String[]{"a", "b"}, new String[]{"c", "d"});

Stream flattenedStream = stringArrays.stream().flatMap(Arrays::stream);

flattenedStream.forEach(System.out::println);

// 输出a, b, c, d

}

}

sorted () 和 sorted (Comparator comparator):

功能:用于对 Stream 中的元素进行排序。无参数的 sorted () 方法要求元素实现 Comparable 接口,它会按照元素的自然顺序进行排序。而带有 Comparator 参数的 sorted 方法可以根据自定义的比较规则进行排序。示例:假设有一个包含整数的 List,要按照降序排序。

import java.util.Arrays;

import java.util.Comparator;

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List numbers = Arrays.asList(3, 1, 4, 1, 5, 9);

Stream sortedStream = numbers.stream().sorted(Comparator.reverseOrder());

sortedStream.forEach(System.out::println);

// 输出9, 5, 4, 3, 1, 1

}

}

终端操作方法

forEach(Consumer action):

功能:用于遍历 Stream 中的每个元素,并对每个元素执行一个操作。这个操作由 Consumer(消费者)函数来定义,它是一个接收一个参数并且没有返回值的函数。示例:假设有一个包含字符串的 List,要打印出每个字符串。

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List words = Arrays.asList("hello", "world");

Stream stream = words.stream();

stream.forEach(System.out::println);

// 输出hello和world

}

}

count():

功能:返回 Stream 中元素的数量。示例:假设有一个包含整数的 List,要计算元素的个数。

import java.util.Arrays;J

import java.util.List;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List numbers = Arrays.asList(1, 2, 3, 4, 5);

long count = numbers.stream().count();

System.out.println(count);

// 输出5

}

}

collect(Collector collector):

功能:是一个非常强大的终端操作,用于将 Stream 中的元素收集到一个集合或者其他数据结构中。Collectors 类提供了许多预定义的收集器,如 toList、toSet、toMap 等。示例:假设有一个包含整数的 List,要将所有大于 2 的整数收集到一个新的 List 中。

import java.util.Arrays;

import java.util.List;

import java.util.stream.Collectors;

import java.util.stream.Stream;

public class StreamExample {

public static void main(String[] args) {

List numbers = Arrays.asList(1, 2, 3, 4, 5);

List collectedList = numbers.stream().filter(n -> n > 2).collect(Collectors.toList());

System.out.println(collectedList);

// 输出[3, 4, 5]

}

}