引子:Stream API的出现,显著推进了Java对函数式编程的支持。它允许开发者可以用声明式Declarative的方式处理数据集合(比如列表、数组等),还能有效利用多核处理器进行并行操作,提升应用程序的性能,同时保持代码简洁易读。
1. Stream API的介绍
Stream API的引入,为数据集合的操作提供了一种新的范式。Stream本身并不是数据结构,不会存储数据或改变数据源,它仅定义处理方式,可以视为一种高级迭代器,不
仅可以支持顺序处理,还能进行并行处理,为集合的过滤、映射、聚合等操作提供了一种高效的实现方式。
2. Stream 的操作
要掌握和有效使用Stream API,关键在于理解其三个核心步骤:
创建流Stream Creation:流可以从多种数据源创建,包括集合、数组、文件、I/O通道等等,甚至可以创建无限流。由于Stream本身不是数据结构,这意味着,当你创建一个Stream实例的时候,实际的数据仍然存储在原始的数据结构中
中间操作Intermediate Operations:中间操作用于对流中元素进行处理,比如筛选(Filter)、映射(Map)、排序(Sort)等等,每次调用中间操作时,都会返回一个新的流,从而支持链式调用,可以构建复杂的查询和数据处理策略。PS:中间操作是惰性执行的,意味着他们不会立即执行,直到遇到终端操作才会实际执行。
终端操作Terminal Operations:终端操作是整个流处理的实际执行部分,它会触发所有之前定义的中间操作,并生成最终结果,比如收集数据到集合中,执行规约、聚合统计以及遍历元素等任务。执行终端操作后,流中的元素会被消费,流就不能再被使用了。
2.1 创建流
从集合创建流:对于任何实现了Collection接口的集合,比如List、Set可以通过stream方法直接创建一个Stream流
List<Stream> list = List.of("a", "b", "c");
Stream<Stream> Stream = list.stream();
stream.forEach(System.out::println);
通过数组(Arrays)创建流:可以使用Arrays工具类的stream方法来实现
String[] array = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(array);
stream.forEach(System.out::println);
通过Stream.of方法:直接从一组值创建一个流
Stream<String> stream = Stream.of("a", "b", "c");
stream.forEach(System.out::println);
合并两个流可以使用concat方法:他会按照两个流的顺序将两个流连接起来
Stream<String> stream1 = Stream.of("a", "b", "c");
Stream<String> stream2 = Stream.of("e", "f", "g");
Stream<String> concat = Stream.concat(stream1, stream2);
concat.forEach(System.out::println);
动态的构建流可以使用流构建器(StreamBuilder),它可以根据特定条件,动态的决定是否将元素加入流中
Stream.Builder<String> streamBuilder = Stream.builder();
streamBuilder.add("a");
streamBuilder.add("b");
Stream<String> stream = streamBuilder.build();
另外要注意的是:如果一旦调用了build方法就不能再向streamBuilder里面添加更多元素,尝试这样做会抛出IllegalStateException
从文件创建流:特别适合与文本分析,日志文件处理等场景,我们可以通过Java的Files类的lines方法来实现
Path path = Paths.get("file.txt");//获取文件路径
try (Stream<String> lines = Files.line(path)) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.getStackTrace();
};//他会逐行读取文件内容,每行文本都会被当作一行字符串处理,然后将其作为元素放入流中
值得注意的是,使用该方法打开的文件资源,必须被妥善关闭,以避免资源泄漏,为此推荐将此方法封装在try with resource语句里面,这样可以自动确保,无论处理过程如何,文件资源都得以妥善关闭
对于基本类型的处理Stream API专门提供了IntStream、LongStream、DoubleStream来分别处理int、long、double类型,以下通过IntStream来演示:
可以通过of、range、rangeClosed等方法静态的创建
评论区