什么是 Stream 流
定义:Stream 是 Java 8 中引入的一个新的抽象层,它可以让你以一种声明式的方式处理集合(Collection)数据。简单来说,它就像是一条流水线,数据(集合中的元素)在这条流水线上流动,并且可以在流动的过程中进行各种操作,如过滤、映射、排序等。特点:
惰性求值:Stream 流操作分为中间操作和终端操作。中间操作只是定义了对数据的处理方式,并不会立即执行,只有当终端操作被调用时,整个 Stream 流的操作才会真正执行。例如,你定义了一个过滤操作和一个计数操作,只有当你执行计数操作(终端操作)时,过滤操作(中间操作)才会被执行。不可变数据:Stream 流本身不会修改数据源。它返回的是一个新的 Stream 或者一个计算结果,而原始的数据集合不会被改变。函数式编程风格:Stream API 大量使用了 Lambda 表达式,这使得代码更加简洁和易于理解。你可以将操作看作是对数据集合的一系列函数调用。Stream 流常用的方法
中间操作方法
filter(Predicate super T> 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
Stream
// 此时还没有真正执行过滤操作,因为filter是中间操作
evenNumbersStream.forEach(System.out::println);
// 当执行终端操作forEach时,filter操作才会被执行,输出2, 4, 6
}
}
map(Function super T,? extends R> 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
Stream
lengthsStream.forEach(System.out::println);
// 输出3, 6, 6,因为"apple"长度为3,"banana"长度为6,"cherry"长度为6
}
}
flatMap(Function super T,? extends Stream extends R>> 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
Stream
flattenedStream.forEach(System.out::println);
// 输出a, b, c, d
}
}
sorted () 和 sorted (Comparator super T> 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
Stream
sortedStream.forEach(System.out::println);
// 输出9, 5, 4, 3, 1, 1
}
}
终端操作方法
forEach(Consumer super T> 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
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
long count = numbers.stream().count();
System.out.println(count);
// 输出5
}
}
collect(Collector super T,A,R> 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
List
System.out.println(collectedList);
// 输出[3, 4, 5]
}
}