Java Stream流

Stream流

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

结合Lambda表达式来完成某种功能的实现

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

以上流程转化为Java代码为:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();

什么是Stream?

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

生成流

在 Java 8 中, 集合接口有两个方法来生成流:

  • stream() − 为集合创建串行流。(单线程)
  • parallelStream()− 为集合创建并行流。(多线程)

举个例子

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

image-20240604221707954

方法

Stream()

生成流

forEach()

void forEach(Consumer<? super String> action)

  • 用来遍历集合或者数组....

Consumer这个接口下一篇进行介绍,简单字面意思就是,你给它传什么的,他就消费什么(就是输出)

List<String> strings3 = Arrays.asList("cwy","cwy","wst","wst","cwy");
//遍历strings3
strings3.forEach(System.out::println);

image-20240604223021420

image-20240604222353301

map()

< R> Stream< R> map(Function<? super T, ? extends R> mapper);

  • map 方法用于映射每个元素到对应的结果

,嗯...有点类似于一元函数映射

Function 接口是一个功能型接口,它的一个作用就是转换作用,将输入数据转换成另一种形式的输出数据。

//        把xList中的数值  进行平方运算映射在yList
List<Integer> xList = Arrays.asList(1,2,3,4,5,6,7,8,9);
List<Integer> yList = xList.stream().map(integer -> integer*integer).distinct().collect(Collectors.toList());
System.out.println(yList);

image-20240604224900043

filter()

Stream<T> filter(Predicate<? super T> predicate);

filter 方法用于通过设置的条件过滤出元素

//        获取空字符串的数量
long count = strings4.stream().filter(String::isEmpty).count();
System.out.println(count);

image-20240604232504042

limit()

Stream<T> limit(long maxSize);

limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:

//      取出集合前两个元素
List<String> strings5 = Arrays.asList("cwy","cwy","wst","wst","cwy");
strings5.stream().limit(2).forEach(System.out::println);
//        or
List<String> limits =strings5.stream().limit(2).collect(Collectors.toList());
System.out.println(limits);

image-20240604233019073

sorted()

sorted 方法用于对流进行排序。

IntStream sorted();

//        使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

ints()

源码 用来生成整数流

public IntStream ints() {
        return StreamSupport.intStream
                (new RandomIntsSpliterator
                         (this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
                 false);
    }

并行(parallel)程序

parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:(使用的是多线程)

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

使用并行的程序可以提升处理速度

//        获取空字符串的数量
long date1 = new Date().getTime();
long count = strings4.stream().filter(String::isEmpty).count();
long date2 = new Date().getTime();
System.out.println(count+"所用时间"+(date2-date1));

//          获取空字符串的数量
long date3 = new Date().getTime();
List<String> strings6 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
long date4 = new Date().getTime();
long count2 = strings6.parallelStream().filter(String::isEmpty).count();
System.out.println(count2+"所用时间"+(date4-date3));

image-20240604234153199

建议:数据量不大的情况下建议使用stream即可,不要盲目大量使用parallelStream,因为parallelStream是多线程异步的,也就是说会产生多线程,消耗内存不说,说不定还会更慢,并非一定会更快更好。

Collectors

Collectors 类实现了很多归约操作

//        Collectors
List<String>strings7 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered7 = strings7.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings7.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);

image-20240604234940132

统计相关函数

        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

        IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());

image-20240604235321302

完整实例

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");
//        写Stream流
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        System.out.println(filtered);
//        过滤cwy
        List<String> strings1 = Arrays.asList("cwy","cwy","wst","wst","cwy");
        List<String> collect = strings1.stream()
                        .filter(s -> s.equals("wst")).collect(Collectors.toList());
        System.out.println(collect);
//        forEach
        List<String> strings3 = Arrays.asList("cwy","cwy","wst","wst","cwy");
        strings3.forEach(System.out::println);
//        map
//        把xList中的数值  进行平方运算映射在yList
        List<Integer> xList = Arrays.asList(1,2,3,4,5,6,7,8,9);
        List<Integer> yList = xList.stream().map(integer -> integer*integer).distinct().collect(Collectors.toList());
        System.out.println(yList);


//      取出集合前两个元素
        List<String> strings5 = Arrays.asList("cwy","cwy","wst","wst","cwy");
        strings5.stream().limit(2).forEach(System.out::println);
//        or
        List<String> limits = strings5.stream().limit(2).collect(Collectors.toList());
        System.out.println(limits);
//        使用 sorted 方法对输出的 10 个随机数进行排序:
        Random random = new Random();
        random.ints().limit(10).sorted().forEach(System.out::println);

        //        获取空字符串的数量
        long date1 = new Date().getTime();
        List<String>strings4 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        long count = strings4.stream().filter(String::isEmpty).count();
        long date2 = new Date().getTime();
        System.out.println(count+"所用时间"+(date2-date1));

        //          获取空字符串的数量
        long date3 = new Date().getTime();
        List<String> strings6 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        long date4 = new Date().getTime();
        long count2 = strings6.parallelStream().filter(String::isEmpty).count();
        System.out.println(count2+"所用时间"+(date4-date3));
//        Collectors
        List<String>strings7 = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> filtered7 = strings7.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

        System.out.println("筛选列表: " + filtered);
        String mergedString = strings7.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("合并字符串: " + mergedString);

        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

        IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());
    }
}
posted @   Yang0710  阅读(143)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
世间美好与你环环相扣 - 柏松
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 尹初七

作曲 : 柏松

编曲 : 彭圣杰

偏偏秉烛夜游

偏偏秉烛夜游

午夜星辰 似奔走之友

爱你每个结痂伤口

酿成的陈年烈酒

入喉尚算可口

入喉尚算可口

怎么泪水 还偶尔失守

邀你细看心中缺口

裂缝中留存 温柔

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

让樱花偷偷 吻你额头

让世间美好 与你环环相扣

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

当樱花开的纷纷扬扬

当世间美好 与你环环相扣

特别鸣谢:槿葵,我们的海报制作妹妹。

原唱:柏松

吉他:柏松

和声:柏松

录音:柏松

混音:张强

点击右上角即可分享
微信分享提示