Java流式编程stream
创始人
2024-01-16 12:22:00
0

文章目录

      • 一、简介
      • 二、创建Stream
      • 三、常用操作
      • 四、其他操作


image-20220809112034032

一、简介

  1. 流式 API 从 Java8 开始引入,支持链式书写。

  2. 流只能消费一次,不能被两次消费(两次最终操作)

  3. 流在管道中流通,在节点被处理。

  4. 流【无存储】,流不是一种数据结构,流存储的只是一种数据视图。

  5. Stream是独特的,既不同于io,也不同于List。

  6. Stream 不是 InputStream/OutputStream,它俩首先不在同一个包,其次概念上也不一样,Stream代表的是任意Java对象的序列。

    • java.util.stream

    • java.io

      image-20220809073626906

  7. Stream 不是 List,List中存储的元素是事先存在于内存中的Java对象,而Stream输出的元素可能并没有预先存储在内存中,而是通过实时计算出来的惰性对象。其次,Stream在理论上能容纳无限对象,List不能。

  8. 简单流式计算:

    cat.map(n -> n.multiply(n)).limit(100).forEach(System.out::println);
    
  9. 流式计算特点:

    • 惰性计算,真正的计算通常只发生在最后的结果获取时。流式计算存在第一步、中间一步、最后一步的说法,只有当到达最后一步执行函数的时候,整个惰性函数才会执行。

    • 一个Stream可以轻易转换为另一个Stream。

    • 存在泛型接口,需要指明使用对象。

    • 流式计算应该和 Lambda 表达式一起使用,符合Java8的思想(两者同时升级出现)。

      cat.filter(n -> n % 2 == 0) // 不计算.map(n -> n * n) 				// 不计算.limit(100) 							// 不计算.sum(); 									// 计算
      
  10. 常用操作举例

中间操作最终操作
mapforEach
filtercollect
limitcount
sorted
distinct
  1. 【无限序列】说明

    ​ 对于无限序列,如果直接调用 forEach() 或者 count() 求最终值,会直接进入死循环,因为无限序列永远不可能被计算完。所以我们需要先将起转变为有序序列,例如limit(100)。

  2. 【并行计算】

    • 使用十分简单。

    • 正常情况下,Stream为单线程,现在我们想要多线程。

    • parallel(),自动转化多线程。

      stream.parallel().sorted() .toArray(String[]::new);
      

二、创建Stream

4种方法,

其中第1、2种方式创建出来的流顺序是固定的,3、4不固定。

  1. of():最简单的方法

    Stream stream = Stream.of("a","b","c");
    stream.forEach(System.out::println);
    
  2. Collection:进阶

    // 方式一,Collection直接调用stream方法
    List list = List.of("a","b","c");
    Stream stream = list.stream();// 方式二,利用Arrays(本质和方式一差不多)
    Stream s = Arrays.stream(new String[] { "A"});
    
  3. Supplier(“暗示”,存储算法):采用Stream.generate(),传入Supplier对象。基于Supplier创建的Stream会不断调用Supplier.get()方法来生成下一个元素,这种Stream中保留的不是元素,而是算法。范例:

    Stream my = Stream.generate(new MySup());
    my.limit(10).forEach(System.out::println);// 不断生成自然数的Supplier(范围在Integer之内)
    class MySup implements Supplier {int n = 0;public Integer get() {n++;return n;}
    }
    
  4. 其他API接口

    • Files类的lines()方法,常用于遍历文本文件。
    • 正则表达式Pattern对象存在 splitAsStream() 方法,可以直接把一个长字符串分割成Stream序列而不是数组。

三、常用操作

  1. 【三种】基本类型流

    ​ 在Java中,因为Java泛型不支持基本类型,所以我们无法使用像Stream这样的形式来保存int,只能采用形如Integer这样的形式。但是频繁装箱、拆箱操作会牺牲编译器的大量性能。

    ​ 所以为了提高效率,Java标准库提供了三种使用基本类型的Stream,它们的使用和标准的Stream没有太大区别,直接使用:

    • IntStream
    • LongStream
    • DoubleStream
    // 1. 
    IntStream is = Arrays.stream(new int[] { 1, 2, 3 });// 2. 将Stream转换为LongStream:
    LongStream s=List.of("1").stream().mapToLong(Long::parseLong);
    
  2. ==map()==方法简介

    • 映射操作,它将一个Stream转换为另一个Stream。
    • 每一次映射都会自赋值,形如:a = a + 1,所以不再需要编写复制语句(思想)。
    Stream s1 = Stream.of(1,2,3);Stream s2 = s1.map(n->n*n);
    s2.forEach(System.out::println);
    
    • 如果我们查看Stream的源码,会发现map()方法接收的对象是Function接口对象,它定义了一个apply()方法,负责把一个T类型转换成R类型:
     Stream map(Function mapper);
    
    @FunctionalInterface
    public interface Function {// 将T类型转换为R:R apply(T t);
    }
    
    • map运算的综合应用案例
    List.of("  Apple ", " pear ").stream() 												// 转换为Stream.map(String::trim) 								// 去空格.map(String::toLowerCase)					// 变小写.forEach(System.out::println); 		// 打印
    
  3. ==forEach()==遍历

    stream.forEach(System.out::println);
    
  4. filter():过滤,true则通过。

    IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)// 注意lambda的编写形式.filter(n -> n % 2 != 0).forEach(System.out::println);
    
  5. ==reduce()==方法简介

    • reduce()是聚合方法,map和filter是转换方法。

      • 转换方法:元素一一对应并转换。非“最终方法”,不会触发计算。
      • 聚合方法:合并计算所有值,得到一个最终结果。“最终方法”,会触发计算操作。
    • reduce()方法传入的对象是BinaryOperator接口实现,它定义了一个apply()方法,负责把上次累加的结果和本次的元素进行运算,并返回累加的结果。

    • 使用较为复杂,暂时跳过。

    @FunctionalInterface
    public interface BinaryOperator {// Bi操作:两个输入,一个输出T apply(T t, T u);
    }
    
  6. ==collect()==方法简介:将Stream转化为集合。

    // 1. 过滤空白字符并转为 ArrayList
    stream.filter(s -> s != null && !s.isBlank()).collect(Collectors.toList());// 2. 转为 Set
    stream.collect(Collectors.toSet());// 3. 转为 Map,先 key 后 value
    Stream stream = Stream.of("APPL:Apple");Map map = stream.collect(Collectors.toMap(s -> s.substring(0, s.indexOf(':')),s -> s.substring(s.indexOf(':') + 1)));
    
  7. ==toArray()==方法简介:将Stream转化为数组。

    String[] array = list.stream().toArray(String[]::new);
    

四、其他操作

  1. collect分组输出

    • 实际.collect()方法。
    • 用途:导入学生名单,然后按班级分类输出。
    List list = List.of("Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots");Map> g = list.stream().collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));System.out.println(groups);
    //输出:{A=[Apple, Avocado, Apricots], B=[Banana, Blackberry], C=[Coconut, Cherry]}
    
  2. sorted排序(两种方式)

    • 已经实现comparable接口的,直接使用;
    • 自定义Comparator比较器。

    【注意sordted只是转换操作,只会返回新的Stream而不会修改原来的Stream】

    // 无“自赋值”
    stream = stream.sorted(); 
    stream = stream.sorted(String::compareToIgnoreCase);
    
  3. distinct去重

    // 无“自赋值”
    stream = stream.distinct();
    
  4. limit截取:从头开始截取。

    // 无“自赋值”
    stream = stream.limit(20);
    
  5. skip: 扔掉前面几个元素。

    stream = stream.skip(5)
    
  6. concat合并流

    Stream s1 = ... ;
    Stream s2 = ... ;Stream s3 = Stream.concat(s1,s2);
    
  7. flatMap平面化:将“三维数据”转化为“二维数据”。

    image-20220809103915928
    Stream< List > s = Stream.of(Arrays.asList(1, 2, 3),Arrays.asList(4, 5, 6),Arrays.asList(7, 8, 9));Stream i = s.flatMap(list -> list.stream());
    
  8. 数学计算

    • count():返回元素个数。
    • max(Comparator cp):找出最大元素。
    • min(Comparator cp):找出最小元素。
    • sum():对所有元素求和,只适用于数值类型。
    • average():对所有元素求平均数。
  9. 匹配

    • boolean allMatch(Predicate):所有元素均满足测试条件。
    • boolean anyMatch(Predicate):至少有一个元素满足测试条件。
  10. 复合实例

Stream ds= Stream.of(
new Student("zhang",99.6),
new Student("qian",78.12),
new Student("sun",59.9),
new Student("sun",60.0));ds.filter(stu -> stu.getScore()<60.0).forEach(System.out::println);

上一篇:

下一篇:熊毛衣

相关内容

热门资讯

壁虎观察日记 壁虎观察日记(精选23篇)  转眼一天又过去了,今天我们都做了什么了呢?这时候,最关键的日记怎么能落...
蚂蚁童话作文400字 【必备】蚂蚁童话作文400字3篇  无论在学习、工作或是生活中,大家最不陌生的就是作文了吧,作文是人...
我喜欢的小动物作文 我喜欢的小动物作文(精选40篇)  在日常学习、工作或生活中,大家对作文都不陌生吧,作文是人们以书面...
蚂蚁的观察日记 蚂蚁的观察日记 (精选21篇)  一天的时间眼看就要结束了,想必有很多难忘的瞬间吧,此时此刻我们需要...
提升自己作文 提升自己作文(通用49篇)  在平时的学习、工作或生活中,大家都跟作文打过交道吧,作文根据体裁的不同...
猫和老鼠 猫和老鼠猫和老鼠1  有一只小花猫,她叫喵喵。她非常挑食,这个也不爱吃,那个也吃不下。她有个邻居,是...
我和童话人物的一天作文 我和童话人物的一天作文(精选26篇)  在日复一日的学习、工作或生活中,大家都写过作文,肯定对各类作...
战争中的孩子的作文 战争中的孩子的作文(精选35篇)  无论在学习、工作或是生活中,大家都接触过作文吧,作文可分为小学作...
我学会了煎鸡蛋作文 我学会了煎鸡蛋作文(精选104篇)  在日常学习、工作或生活中,大家或多或少都会接触过作文吧,作文要...
说说我的心里话作文500字 说说我的心里话作文500字(通用59篇)  在平平淡淡的学习、工作、生活中,大家都经常接触到作文吧,...
未来科幻作文 未来科幻作文(精选20篇)  在现实生活或工作学习中,大家一定都接触过作文吧,作文是经过人的思想考虑...
军训的感受优秀作文 军训的感受优秀作文10篇  在平平淡淡的学习、工作、生活中,大家都写过作文,肯定对各类作文都很熟悉吧...
睡前童话故事哄小朋友短篇 睡前童话故事哄小朋友短篇(精选111篇)  童话故事是指儿童文学的一种体裁,童话中丰富的想象和夸张可...
未来的想象作文 关于未来的想象作文10篇  在学习、工作或生活中,大家总少不了接触作文吧,作文可分为小学作文、中学作...
我学会了做饭作文 我学会了做饭作文(通用13篇)  在生活、工作和学习中,大家都不可避免地要接触到作文吧,作文是一种言...
成就自己的价值作文 成就自己的价值作文(通用43篇)  在现实生活或工作学习中,大家一定都接触过作文吧,作文是一种言语活...
守护树散文作文1200字 守护树散文作文1200字  我出生在一个美丽的村庄。在我3岁时,父母相继去世了。在我的童年里,满是黑...
说说我自己作文 说说我自己作文集锦15篇  随着社交网络的迅猛发展,越来越多人会在网上发布说说,用以记录和分享生活日...
走进信息世界作文400字 走进信息世界作文400字七篇  在学习、工作乃至生活中,大家都不可避免地要接触到作文吧,写作文可以锻...
我变成了一只小鸟作文 我变成了一只小鸟作文300字(精选61篇)  在平时的学习、工作或生活中,大家总少不了接触作文吧,根...