Java流对象stream概述
一、定义与起源
Stream是Java 8 API添加的一个新的抽象概念,称为流(Stream)。它以一种声明性方式处理数据集合,侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式。Stream流是从支持数据处理操作的源生成的元素序列,这些源可以是数组、文件、集合、函数等。Stream流不是集合元素,也不是数据结构,它并不保存数据,主要目的在于计算,是对集合(Collection)对象功能的增强。
二、原理
- 惰性求值:Stream的中间操作是惰性执行的,只有终端操作开始时才会进行计算。这意味着,在调用终端操作之前,中间操作只是对流的操作进行了记录,而并未真正执行。
- 无存储:Stream本身不保存数据,它只会在需要时生成结果。
- 不可变性:Stream本身不可改变,操作Stream时会生成新的Stream。
- 可并行化:通过parallelStream()方法,可以很方便地进行并行操作,利用多核CPU提高性能。
Stream的工作方式是惰性求值,中间操作如map、filter等只是记录操作,而不立即执行。流的终端操作如collect则会触发整个操作链的执行。每个流的操作会以流水线方式运行,数据会依次通过这些流水线,从而提高处理效率。
三、方法
Stream的API由三部分组成:数据源、链式中间操作、终端操作。
数据源:Stream的数据源可以是集合、数组、I/O通道等。
你可以从多种来源创建流:
-
- 集合框架:如
List
,Set
等可以通过.stream()
或.parallelStream()
方法创建流。
- 集合框架:如
- 数组:使用
Arrays.stream(array)
。 - 文件:
Files.lines(path)
可以从文件中读取行作为流。 - 生成器:
Stream.generate(Supplier<T> s)
或Stream.iterate(T seed, UnaryOperator<T> f)
用于无限流。 - 静态工厂方法:
Stream.of(...)
。
中间操作:返回新的Stream流,可以链式调用。常见的中间操作有:
filter(Predicate<? super T> predicate)
:过滤元素。map(Function<? super T, ? extends R> mapper)
:转换元素。flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
:将每个元素映射为另一个流,然后合并这些流。distinct()
:去除重复元素。sorted()
和sorted(Comparator<? super T> comparator)
:排序元素。limit(long maxSize)
和skip(long n)
:限制和跳过元素。peek(Consumer<? super T> action)
:主要用于调试。
终端操作:触发流的计算,并生成结果。常见的终端操作有:
- forEach(Consumer<? super T> action):对每个元素执行操作。
- toArray():将流收集到数组中。
- collect(Collector<? super T, A, R> collector):根据特定规则收集流中的元素。
- reduce(BinaryOperator<T> accumulator):聚合流中的元素。
- count():计算流中元素的数量。
- anyMatch(Predicate<? super T> predicate), allMatch(Predicate<? super T> predicate), noneMatch(Predicate<? super T> predicate):匹配条件。
- findFirst(), findAny():查找符合条件的第一个元素或任意元素。
四、用途
Stream提供了一种简洁、声明式的方式来操作数据集合,极大地提高了代码的可读性和灵活性。它允许开发者在不改变数据源的情况下进行数据处理,能够轻松执行复杂的查找、过滤、筛选等操作,并且可以链式地组合多个操作,形成一个操作管道。
五、使用场景
- 过滤和排序:可以对集合中的元素进行过滤和排序操作,例如筛选出年龄大于18岁的用户并按姓名排序。
- 并行流处理大数据:对于需要处理大量数据的场景,Stream提供了并行处理的功能,通过parallelStream()方法可以将数据流并行化,提高计算效率。
- 自定义聚合:可以使用reduce()操作来实现自定义聚合操作,例如字符串拼接等。
六、各方法示例
- filter方法示例:
List<String> list = Arrays.asList("a", "", "b", "", "cc", "x", "dd"); list.stream().filter(item -> !item.trim().isEmpty()).forEach(System.out::println);
这段代码使用filter方法过滤出非空字符串,并打印出来。
- map方法示例:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); list.stream().map(x -> x * x).forEach(System.out::println);
这段代码使用map方法将每个元素映射为其平方数,并打印出来。
- sorted方法示例:
这段代码使用sorted方法对流中的元素进行自然排序,并将结果收集到List中打印出来。
List<Integer> list = Arrays.asList(1, 3, 4, 2, 6, 2); List<Integer> collect = list.stream().sorted().collect(Collectors.toList()); System.out.println(collect);
- parallelStream方法示例:
List<Integer> numbers = IntStream.rangeClosed(1, 1000000).boxed().collect(Collectors.toList()); int sum = numbers.parallelStream().reduce(0, Integer::sum); System.out.println("Sum: " + sum);
这段代码使用parallelStream方法将数据流并行化,并计算所有元素的和。
综上所述,Java中的Stream流对象是一种强大的数据处理工具,它提供了丰富的操作方法来处理数据集合,并能够充分利用多核处理器的性能进行并行处理。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!