侧边栏壁纸
  • 累计撰写 9 篇文章
  • 累计创建 5 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

Java中的流、并行流--Java Stream API | Parallel Streams

Lieey
2024-06-10 / 1 评论 / 0 点赞 / 96 阅读 / 4115 字

引子: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等方法静态的创建

0

评论区