目录
一、Stream 流是什么,为啥它如此重要
二、Stream 流的创建
1. 通过集合创建
2. 通过数组创建
3. 使用 Stream.of () 方法
三、Stream 流的中间操作
1. 过滤(filter)
2. 映射(map)
3. 排序(sorted)
四、Stream 流的终端操作
1. 收集(collect)
2. 聚合(reduce)
3. 查找(findFirst、findAny 等)
五、并行流的应用
六、总结
在 Java 编程的领域中,Stream 流可谓是一项令人瞩目的特性,它为我们处理集合数据带来了全新的思路与高效的方式。Stream 流就像是一条数据处理的 “流水线”,让我们能够以一种简洁、声明式的风格对数据进行筛选、转换、聚合等操作。今天,咱们就一起深入探究 Java 的 Stream 流,通过丰富的代码示例来领略它的强大魅力。
一、Stream 流是什么,为啥它如此重要
想象一下,你有一堆杂乱无章的物品,需要对它们进行分类、筛选、统计等一系列操作。以往,我们可能需要编写冗长的循环代码来实现这些功能,不仅繁琐,而且容易出错。而 Stream 流就像是一个智能的 “助手”,它能够帮我们更优雅、更高效地完成这些任务。
Java 8 引入的 Stream 流,本质上是对集合数据进行函数式操作的一种抽象。它允许我们以一种类似于 SQL 语句的方式来处理集合数据,将数据处理逻辑与数据本身分离,使代码更加简洁、易读。通过 Stream 流,我们可以轻松地实现对集合的过滤、映射、排序、聚合等常见操作,大大提高了代码的可读性和可维护性。
二、Stream 流的创建
在使用 Stream 流之前,我们首先要学会如何创建它。Stream 流的创建方式多种多样,下面为大家介绍几种常见的创建方式。
1. 通过集合创建
Java 中的集合类都提供了stream()
方法来创建一个顺序流,以及parallelStream()
方法来创建一个并行流。并行流利用多核 CPU 的优势,能够同时处理多个数据元素,提高处理效率。
java">import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;public class StreamFromCollectionExample {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();numbers.add(1);numbers.add(2);numbers.add(3);numbers.add(4);numbers.add(5);// 创建顺序流Stream<Integer> sequentialStream = numbers.stream();// 创建并行流Stream<Integer> parallelStream = numbers.parallelStream();}
}
2. 通过数组创建
我们可以使用Arrays.stream()
方法将数组转换为 Stream 流。
java">import java.util.Arrays;
import java.util.stream.Stream;public class StreamFromArrayExample {public static void main(String[] args) {int[] numbers = {1, 2, 3, 4, 5};Stream<int[]> streamOfArrays = Stream.of(numbers);// 对于基本类型数组,也可以使用专门的方法IntStream intStream = Arrays.stream(numbers);}
}
3. 使用 Stream.of () 方法
Stream.of()
方法可以直接将一组元素转换为 Stream 流。
java">import java.util.stream.Stream;public class StreamOfExample {public static void main(String[] args) {Stream<String> stringStream = Stream.of("apple", "banana", "cherry");}
}
三、Stream 流的中间操作
Stream 流提供了一系列的中间操作,这些操作会返回一个新的 Stream 流,并且可以将多个中间操作串联起来,形成一个操作链。常见的中间操作包括过滤、映射、排序等。
1. 过滤(filter)
filter
操作可以根据给定的条件筛选出符合条件的元素。
java">import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamFilterExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());System.out.println("偶数: " + evenNumbers);}
}
在上述代码中,我们使用filter
方法筛选出了列表中的偶数。
2. 映射(map)
map
操作可以将 Stream 流中的每个元素按照指定的函数进行转换。
java">import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamMapExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);List<Integer> squaredNumbers = numbers.stream().map(n -> n * n).collect(Collectors.toList());System.out.println("平方后的数字: " + squaredNumbers);}
}
这里我们使用map
方法将列表中的每个数字转换为其平方。
3. 排序(sorted)
sorted
操作可以对 Stream 流中的元素进行排序。
java">import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamSortedExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());System.out.println("排序后的数字: " + sortedNumbers);}
}
在这个例子中,我们对列表中的数字进行了升序排序。如果需要降序排序,可以使用sorted(Comparator.reverseOrder())
。
四、Stream 流的终端操作
终端操作会消费 Stream 流,执行中间操作链,并返回一个结果。常见的终端操作包括收集、聚合、查找等。
1. 收集(collect)
collect
操作可以将 Stream 流中的元素收集到一个集合中,或者进行其他形式的汇总。
java">import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;public class StreamCollectExample {public static void main(String[] args) {List<String> fruits = new ArrayList<>();fruits.add("apple");fruits.add("banana");fruits.add("cherry");List<String> upperCaseFruits = fruits.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println("转换为大写后的水果列表: " + upperCaseFruits);}
}
在上述代码中,我们将水果列表中的每个元素转换为大写,并收集到一个新的列表中。
2. 聚合(reduce)
reduce
操作可以对 Stream 流中的元素进行聚合操作,例如求和、求积等。
java">import java.util.Arrays;
import java.util.List;public class StreamReduceExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);int sum = numbers.stream().reduce(0, (a, b) -> a + b);System.out.println("数字之和: " + sum);}
}
这里我们使用reduce
方法对列表中的数字进行求和,初始值为 0。
3. 查找(findFirst、findAny 等)
findFirst
操作可以返回 Stream 流中的第一个元素,findAny
操作可以返回 Stream 流中的任意一个元素(在并行流中,findAny
可能会返回更高效的结果)。
java">import java.util.Arrays;
import java.util.List;
import java.util.Optional;public class StreamFindExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);Optional<Integer> firstNumber = numbers.stream().findFirst();firstNumber.ifPresent(System.out::println);}
}
在上述代码中,我们使用findFirst
方法获取列表中的第一个元素,并通过ifPresent
方法进行处理,避免了空指针异常。
五、并行流的应用
并行流利用多核 CPU 的优势,可以显著提高大数据集的处理效率。在使用并行流时,只需要将stream()
方法替换为parallelStream()
方法即可。
java">import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class ParallelStreamExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<Integer> squaredNumbers = numbers.parallelStream().map(n -> n * n).collect(Collectors.toList());System.out.println("并行处理后的平方数字: " + squaredNumbers);}
}
需要注意的是,并行流并不适用于所有场景,在处理小数据集或者存在共享资源的情况下,并行流可能会因为线程调度等开销而降低性能。因此,在实际应用中,需要根据具体情况进行权衡。
六、总结
通过今天的学习,我们深入了解了 Java 的 Stream 流,从它的创建方式,到丰富的中间操作和终端操作,以及并行流的应用。Stream 流为我们提供了一种简洁、高效的方式来处理集合数据,让代码更加优雅、易读。在实际编程中,合理运用 Stream 流能够大大提高开发效率,减少代码量,同时充分发挥多核 CPU 的性能优势。希望大家在今后的 Java 编程中,能够熟练掌握并运用 Stream 流,为自己的代码注入新的活力。如果在学习过程中遇到任何问题,欢迎随时交流,让我们一起在 Java 编程的道路上不断探索前行。