JDK1.8 详解java.util.stream.Stream:Stream
介绍:
java.util.stream.Stream是Java 8引入的用于处理集合数据的API。它提供了一种函数式编程风格的操作方式,如过滤、映射、排序和归约等
详细解释和说明:
流(Stream)的概念:流是一系列元素的集合,它可以来自于数组、集合或其他数据源。流提供了一种高级抽象,允许以声明性的方式操作数据,而无需关心底层的实现细节。
流的特点:流具有以下几个特点:
流不存储数据,它只是对数据进行操作和处理。
流的操作可以是顺序的或并行的,使得可以更好地利用多核处理器的优势。
创建流:可以通过各种方式来创建流,包括从集合、数组、I/O通道等。
流的操作:流提供了一系列的中间操作和终端操作来对数据进行处理和操作。常见的操作包括过滤、映射、排序、去重、截取、归约等。
中间操作和终端操作:流的操作可以分为中间操作和终端操作两种类型。中间操作返回一个新的流,可以进行链式调用,而终端操作返回一个结果或副作用,终止了流的操作。
常用的Stream方法:Stream提供了许多常用的方法,如filter()、map()、sorted()、distinct()、limit()、forEach()、reduce()、collect()等,这些方法可以组合使用,以实现复杂的数据处理逻辑。
并行流:通过并行流,可以将数据的处理操作并行化,利用多核处理器的优势来提高性能。使用并行流时需要注意线程安全性和性能问题(并行流顺序流介绍)。
Stream与集合的区别:Stream与传统的集合操作相比,具有更高的抽象级别和表达能力。它可以提供更简洁、灵活、可读性强的代码,同时还可以更好地支持并行处理和延迟求值等特性。
Stream接口的定义:
```java
public interface Stream<T> extends BaseStream<T, Stream<T>> {
// ...
}
Stream接口继承自BaseStream接口,BaseStream接口定义了一些基本的流操作方法。
在Stream接口中,有许多用于操作流的方法,包括过滤、映射、排序、归约等。下面是一些常用的方法示例:
filter(Predicate<? super T> predicate):过滤流中的元素,只保留满足给定谓词条件的元素。
map(Function<? super T, ? extends R> mapper):对流中的每个元素应用一个函数,并将结果存储在新的流中。
sorted():对流中的元素进行排序,默认使用自然排序。
distinct():去除流中的重复元素。
limit(long maxSize):截取流中的前N个元素。
forEach(Consumer<? super T> action):对流中的每个元素执行给定的操作。
reduce(BinaryOperator<T> accumulator):使用给定的二进制操作符对流中的元素进行归约操作。
collect(Collector<? super T, A, R> collector):将流中的元素收集到一个结果容器中。
这些方法使得我们可以通过链式调用来对流进行一系列操作,从而实现复杂的数据处理逻辑。
Stream还提供了一些终端操作方法,用于触发流的计算和获取最终的结果,如forEach、reduce、collect等。
Stream的实现类包括ReferencePipeline、IntPipeline、LongPipeline和DoublePipeline等。这些实现类负责具体的流操作和流数据的处理。
注意:
惰性求值:Stream的操作是惰性求值的,只有在终端操作被调用时才会执行。因此,在编写代码时要注意确保至少有一个终端操作,否则中间操作不会执行。
线程安全性:并行流操作涉及多线程处理数据,因此要注意确保操作中的代码是线程安全的。避免在操作过程中修改共享的可变状态。
性能考虑:并行流可以利用多核处理器的优势,但并不意味着在所有情况下都比顺序流更快。在使用并行流时,要根据具体情况进行性能测试和评估,确保它能够带来性能上的提升。
流的重用:流一般是单次使用的。如果需要对同一组数据执行多个操作,应该创建多个流,而不是尝试在同一个流上多次调用终端操作。
以下是一些简单的代码示例:
public static void main(String[] args) {
//filter(Predicate<? super T> predicate):过滤流中的元素,只保留满足给定谓词条件的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> filteredNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
System.out.println(filteredNumbers);
// 输出: [2, 4]
//map(Function<? super T, ? extends R> mapper):对流中的每个元素应用一个函数,并将结果存储在新的流中。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Integer> nameLengths = names.stream()
.map(String::length)
.collect(Collectors.toList());
System.out.println(nameLengths);
// 输出: [5, 3, 7]
//sorted():对流中的元素进行排序,默认使用自然排序
List<Integer> numbers1 = Arrays.asList(5, 2, 1, 4, 3);
List<Integer> sortedNumbers = numbers1.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedNumbers);
// 输出: [1, 2, 3, 4, 5]
//distinct():去除流中的重复元素。
List<Integer> numbers2 = Arrays.asList(1, 2, 2, 3, 3, 4, 5, 5);
List<Integer> distinctNumbers = numbers2.stream()
.distinct()
.collect(Collectors.toList());
System.out.println(distinctNumbers);
// 输出: [1, 2, 3, 4, 5]
//limit(long maxSize):截取流中的前N个元素。
List<Integer> numbers3 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers3.stream()
.limit(3)
.collect(Collectors.toList());
System.out.println(limitedNumbers);
// 输出: [1, 2, 3]
//forEach(Consumer<? super T> action):对流中的每个元素执行给定的操作
List<String> names4 = Arrays.asList("Alice", "Bob", "Charlie");
names4.stream()
.forEach(System.out::println);
// 输出:
// Alice
// Bob
// Charlie
//reduce(BinaryOperator<T> accumulator):使用给定的二进制操作符对流中的元素进行归约操作。
List<Integer> numbers5 = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers5.stream()
.reduce(0, (a, b) -> a + b);
System.out.println(sum);
// 输出: 15
//collect(Collector<? super T, A, R> collector):将流中的元素收集到一个结果容器中
List<String> names5 = Arrays.asList("Alice", "Bob", "Charlie");
String concatenatedNames = names5.stream()
.collect(Collectors.joining(", "));
System.out.println(concatenatedNames);
// 输出: Alice, Bob, Charlie
}
总结
- Stream提供了一种声明性的方式来操作和处理集合数据,可以使代码更简洁、高效和可读性强。
- 使用中间操作和终端操作的组合,可以构建复杂的数据处理逻辑。
- 并行流可以提高处理大量数据的性能,但要注意线程安全性和性能问题。
- 注意流的惰性求值特性,确保至少有一个终端操作来触发执行。
- 避免在操作过程中修改共享的可变状态,保证线程安全性。
- 流一般是单次使用的,如果需要多次操作同一组数据,应该创建多个流。
- 了解并熟练使用Stream提供的常用方法,如过滤、映射、排序、归约等。
- 结合函数式接口和Lambda表达式,可以更方便地对流进行操作。