java8新特性学习笔记(二) 使用流(各种API)

时间:2022-09-22 11:12:25

筛选和切片

  用谓词筛选,筛选出各个不相同的元素,忽略流中的头几个元素,或将流截断至指定长度

  • 用谓词筛选 Stream接口支持filter方法,该操作接受一个谓词(返回一个boolean的函数) 作为参数,并返回一个包含所有符合谓词的元素的流.
 List<Dish> names = menu.stream()//从菜单中提取流
.filter(Dish::isVegetarian)//筛选 检查菜肴是否适合素食者
.collect(Collectors.toList());//将Stream转化为List
  • 筛选各异的元素 流支持一个叫distinct的方法 他会返回一个元素各异(根据流所生成元素的hashcode和equals方法实现)的流.例如下面代码筛选出列表中所有偶数,并确保没有重复.
   List<Integer> numbers = Arrays.asList(, , , , , , , , , , );
numbers.stream()
.filter(i -> i % == )
.distinct()
.forEach(System.out::println);
  • 截断流 流支持limit(n) 方法,该方法会返回一个不超过给定长度的流,下面代码 选出超过300卡路里的头三道菜
 List<Dish> dishes = menu.stream()
.filter(dish -> dish.getCalories() > )
.limit()
.collect(Collectors.toList());
  • 跳过元素 流支持skip(n)方法,返回一个扔掉了前n个元素的流,如果流中元素不足n个,则返回一个空流.例如 下面的代码将跳过超过300卡路里的头两道菜,并返回剩下的
     List<Dish> dishes = menu.stream()
.filter(dish -> dish.getCalories() > 300)
.skip(2)
.collect(Collectors.toList());

映射

  一个非常常见的数据处理套路就是从某些对象中选择信息,映射成为另外的对象,

  • 对流中的每一个元素应用函数:流支持map方法,他会接受一个函数作为参数.这个函数会应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为他和转换类似,但其中的细微差别在于它是"创建一个新版本" 而不是去修改) 例如下面的例子,就是把方法引用Dish::getName传给了map方法,来提取流中菜肴的名称:
    List<String> disheNames = menu.stream()
.map(Dish::getName)
.collect(Collectors.toList());

  给定一个单词列表,你想要返回另一个列表,显示每个单词有几个字母.代码如下:

      List<String> words = Arrays.asList("Java 8", "Lambda", "In", "Action");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(Collectors.toList());

如果我们想统计没到菜名字的长度呢?大家可以试一试.

  • 流的扁平化

  如何在返回一张列表,列出里面各不相同的字符呢?假定,给定的单词列表是['Hello','World'] 你想要返回列表["H","e","l","o","w","r","d"].

   List<String> words = Arrays.asList("Hello", "World");
List<String[]> stream = words.stream()
.map(word -> word.split(""))
.distinct()
.collect(Collectors.toList());

我们很容易写出上面的代码,但是我们要求返回值是list<String>,但是现在的返回值是List<String[]> 幸好我们可以用flatMap来解决问题!

    List<String> words = Arrays.asList("Hello", "World");
List<String> stream = words.stream()
.map(word -> word.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());

使用flatMap的效果是 各个数组并不是分别映射成一个流,而是映射成流的内容 简而言之就是:flatMap方法让你把一个流中的每个值都换成另一个流,然后把所有的流链接起来成为一个流.

查找和匹配

  查找数据集中的某些元素是否匹配一个给定的属性.

  • 检查谓词是否至少匹配一个元素 anyMatch方法可以做到"流中是否有一个元素匹配给定谓词"
 if(menu.stream().anyMatch(Dish::isVegetarian)) {
System.out.println("menu = " + menu);
}
  • 检查谓词是否匹配所有元素  allMatch方法的工作原理和anyMatch类似 但它会看看流中元素是否都能匹配给定谓词, 如下面代码 所有菜的热量都低于1000卡路里
   boolean b = menu.stream().allMatch(d -> d.getCalories() < 1000);
  • 检查谓词是否不再流中, allMatch相对的是noneMatch,它可以确保流中没有任何元素与给定谓词匹配.
boolean b = menu.stream().noneMatch(d -> d.getCalories() >= 1000);

查找元素

  • findAny方法将返回当前流中的任意元素
  Optional<Dish> any = menu.stream().filter(Dish::isVegetarian).findAny();

这里返回值是Optional<T>类是一个容器,代表一个值存在或者不存在,在上面代码中,findAny可能上面元素都没找到,Java8的库设计人员引入Optional<T>,这样就不用返回众所周知容易出现问题的null了,了解一下Optional里面几种可以迫使你显示的检查指是否存在或者处理值不存在的情形的方法

  1. isPresent() 将在Optional包含值的时候返回true 否则返回false
  2. ifPresent(Consumer<T> block) 会在只存在的时候执行给定代码块
  3. T get()会在值存在时返回值,否则会抛出NoSuchElement异常
  4. T orElse(T other) 会在值存在时返回值,否则返回一个默认值

上面的代码我们可以修改成:

menu.stream()
.filter(Dish::isVegetarian)
.findAny()
.ifPresent(d -> System.out.println("d.get = " + d.getName()));

如果元素存在打印,不存在上面也不做.

  • 查找第一个元素,findFirst() 查找流中第一个元素

何时使用findAny()和findFirst() 答案:并行,找到第一个元素在并行上限制更多,如果你不关心返回的元素是哪个,请使用findAny 因为它在使用并行流时限制较少.

归约

  就是将流中的元素归约成一个值

  • 元素求和 reduce方法 第一个参数是 初始值 第二参数是lambda表达式
Integer[] num = {2, 34, 5};
//有初始值
Integer reduce1 = Stream.of(num).reduce(1, (a, b) -> a + b);// 1+2+34+5
Integer reduce2 = Stream.of(num).reduce(1, Integer::sum);//1+2+34_5
//无初始值
Optional<Integer> reduce3 = Stream.of(num).reduce((a, b) -> a + b);//2+34_5
Optional<Integer> reduce4 = Stream.of(num).reduce(Integer::sum);//2+34_5

当不设置初始值的时候 返回值的时候返回Optional对象,这是因为如果集合为空 那么返回值可能不存在.

 

  • 最大值和最小值 可以用归约函数求最大值或者最小值
     Integer[] num = {2, 34, 5};
//有初始值
Integer reduce1 = Stream.of(num).reduce(1, (a, b) -> a < b ? a : b);
Integer reduce2 = Stream.of(num).reduce(1, (a, b) -> a > b ? a : b);
//无初始值
Optional<Integer> reduce3 = Stream.of(num).reduce(Integer::min);
Optional<Integer> reduce4 = Stream.of(num).reduce(Integer::max);

数值流

  我们在前面看到了可以使用reduce方法计算流中元素的总和,例如 计算菜单的热量

int calories = menu.stream().map(Dish::getCalories).reduce(0, Integer::sum);

这段代码的问题是,他有一个暗含的装箱成本,每个Integer都必须拆箱成一个原始类型再进行求和.

  • 原始类型流特化, Java8引入了三个原始类型特化流来解决这个问题 IntStream DoubleStream LongStream 分别将流中的元素特化int long double,从而避免了暗含的装箱成本.
  1. 映射到数值流 有方法mapToInt mapToLong mapToDouble
  int calories = menu.stream().mapToInt(Dish::getCalories).reduce(0, Integer::sum);
  1. 装换回对象流
   IntStream calories = menu.stream().mapToInt(Dish::getCalories);
Stream<Integer> boxed = calories.boxed();
  1. 默认值OptionalInt 求和是一个很容易的例子,因为它有一个默认值:0,但是如果你计算最大值或者最小值,就要换个法子了 因为0是错误的,如何区分没有元素的流和最大值真是0的流呢? 就需要用到OptionalInt OptionalDouble OptionalLong
OptionalInt max = menu.stream().mapToInt(Dish::getCalories).max();

现在 如果没有最大值的话,你可以显示的处理OptionalInt去定义一个默认值了:

        int i = max.orElse(1);

如果没有默认值的话,显示的提供一个默认最大值

  • 数值范围 和数字打交道,有一个常用的东西就是数值范围,比如,假设你想要生成1和100之间的所有数字,Java8引入了两个可以用于IntStream和LongStream的静态方法,帮助生成这种范围:range和rangeClosed.这两个方法都是第一个参数接受初始值,第二个参数结束值,但是range不包含结束值,而rangeClosed则包含,

java8新特性学习笔记(二) 使用流(各种API)的更多相关文章

  1. java8新特性学习笔记&lpar;二&rpar; 流的相关思想

    流是什么 流是Java API的新成员,他允许你以声明的方式处理数据集合,就现在来说,可以把他们看成遍历数据集合的高级迭代器.此外,流还可以透明地并行处理,你无须写任何多线程代码. 下面例子是新老AP ...

  2. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  3. Java8新特性学习笔记&lpar;一&rpar; Lambda表达式

    没有用Lambda表达式的写法: Comparator<Transaction> byYear = new Comparator<Transaction>() { @Overr ...

  4. java8新特性学习笔记链接

    https://blog.csdn.net/yitian_66/article/details/81010434

  5. Java8 新特性学习 Lambda表达式 和 Stream 用法案例

    Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...

  6. Java8新特性之方法引用&amp&semi;Stream流

    Java8新特性 方法引用 前言 什么是函数式接口 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象.(若 Lambda 表达式抛出一个受检异常(即:非运行 ...

  7. java8新特性学习:函数式接口

    本文概要 什么是函数式接口? 如何定义函数式接口? 常用的函数式接口 函数式接口语法注意事项 总结 1. 什么是函数式接口? 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口 ...

  8. java8新特性学习1

    java8增加了不少新特性,下面就一些常见的新特性进行学习... 1.接口中的方法 2.函数式接口 3.Lambda表达式 4.java8内置的四大核心函数式接口 5.方法引用和构造器引用 6.Str ...

  9. Java8 新特性学习

    摘自:https://blog.csdn.net/shuaicihai/article/details/72615495 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda ...

随机推荐

  1. css3新特性&commat;media&lpar;媒体查询&rpar;

    现在web页面运行的设备的屏幕从pc端到pad,从pad到手机,各种各样,这样就用到了现在经常用到的响应式页面,为实现响应式页面开发,就用到一个非常有用的css3属性media(媒体查询). 介绍:媒 ...

  2. POJ 3067 Japan(经典树状数组)

    基础一维树状数组  题意:左边一排 1-n 的城市,右边一排 1-m 的城市,都从上到下依次对应.接着给你一些城市对,表示城市这两个城市相连,最后问你一共有多少个交叉,其中处于城市处的交叉不算并且每个 ...

  3. C&plus;&plus;基础——子类转父类转子类 (派生类转基类转派生类)

    ==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...

  4. Brainstorm in one sentence

    [1]佚名|*学生占领立法院 人會長大三次 第一次是發現世界不是為自己而轉的時候. 第二次是在發現即使再怎麼努力,終究還是有些事令人無能為力的時候. 第三次是在,明知道有些事可能會無能為力,但還是會 ...

  5. protobuf 系列 ---------下载、编译与使用

    protobuf是谷歌开发并开源的二进制序列化工具,比常用的xml,json体积更小,解析速度更快. 目前,手头上的项目有涉及到这个工具,打算仔细研究一番,顺带记录遇到的问题,解决方法,时间足够的话, ...

  6. python ctrl&plus;c

    #!/usr/bin/env pythonimport signalimport sysimport osdef signal_handler(signal, frame): print('You p ...

  7. Hadoop日记系列目录

    下面是Hadoop日记系列的目录,由于目前时间不是很充裕,以后的更新的速度会变慢,会按照一星期发布一期的原则进行,希望能和大家相互学习.交流. 目录安排 1>  Hadoop日记Day1---H ...

  8. Sharepoint 开启发布功能的PowerShell

    前言 最近,需要一段开启SharePoint站点发布功能的PowerShell命令,因为很多站点批量开启,去网站集功能和网站功能里分别点很麻烦,就搜了这样的命令,如果有需要的可以看一看. $siteU ...

  9. 同步一个 fork

    fork 了别人的仓库后,原作者又更新了仓库,如何将自己的代码和原仓库保持一致?本文将给你解答. 如何使用搜索引擎 其实这个问题并不难,我又被坑了.百度搜的东西不靠谱啊,以后这种问题一定要用英文在 G ...

  10. Android 修改Camera拍照的默认保存路径

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...