美文网首页Java基础知识
JDK8中Stream及Optional学习笔记

JDK8中Stream及Optional学习笔记

作者: 海涛_meteor | 来源:发表于2019-07-17 21:31 被阅读0次

Stream流

普通循环写法,迭代在外部进行
流式写法,迭代由内部控制,内部迭代将更多控制权交给了集合类

Stream的使用非常类似建造者模式

Stream中的方法通常分为以下两种:

  1. 惰性求值:不会进行方法执行,其特征:返回值为stream

  2. 及早求值:会触发方法执行

Stream的常用方法

  • forEach: 迭代
  • map:用新的值替代Stream中的旧值,mapToInt则可以将Stream转化为IntStream
  • flatMap: 把一个流中的每个值都换成另一个流,然后把所有的流连接
    起来成为一个流(将流扁平化)
  • filter:过滤部分Stream中的值
  • distinct: 去除重复元素
  • limit:截取流中指定个数元素
  • skip: 跳过流中指定个数的元素,和limit起到互补作用
  • allMatch/anyMatch/noneMatch: 全部匹配/任意一个匹配/没有匹配,返回boolean
  • findAny/findFirst: 返回任意一个元素/返回第一个元素,返回类型为Optional
  • min&max: 求最大最小值
  • count: 计算个数
  • reduce: 递归操作
  • peek:用于记录日志或查看每一个值

高阶函数:如果函数的参数列表里包含函数接口,或该函数返回一个函数接口,那么该函数就是高阶函数,例如map方法

数值流

数值流包含IntStreamLongStreamDoubleStream,它们避免了隐形的拆箱成本,并且实现了一些独有的数值计算方法,如maxmin/maxaveragerange/rangedsummaryStatistics等,需要转换回对象流可以使用boxed方法,或者mapToObj方法

创建流的方式

  1. 由值创建:
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
  1. 由数组创建:
int[] numbers = {2, 3, 5, 7, 11, 13}; int sum = Arrays.stream(numbers).sum();
  1. 由文件创建:
Stream<String> lines =
Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
  1. 由函数创建:
Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);

Stream.generate(Math::random).limit(5).forEach(System.out::println);

Optional

Optional<T>是一个容器类,代表一个值存在或不存在,使用Optional<T>定义属性的类型可以清楚说明属性是否支持为null

创建Optional对象
  1. 声明一个空的Optional
Optional<Car> optCar = Optional.empty();
  1. 依据一个非空值创建Optional
Optional<Car> optCar = Optional.of(car);
  1. 可接受null的Optional
Optional<Car> optCar = Optional.ofNullable(car);
Optional无法序列化

Optional<T>类型的属性无法序列化,实在需要用到的情况可以采用以下方式

public class Person {
    private Car car;
    public Optional<Car> getCarAsOptional() {
        return Optional.ofNullable(car);
    }
}
Optional的常用方法
  • map/flatMap/filter:与Stream中用法类似
  • get():值存在时返回值,否则抛出一个NoSuchElement异常
  • isPresent():有值则返回true
  • ifPresent(Consumer<T> block):会在值存在的时候执行给定的代码块
  • orElse(T other):值存在时返回值,否则返回一个默认值
  • orElseGet(Supplier<? extends T> other):orElse方法的延迟调用版,Supplier
    方法只有在Optional对象不含值时才执行调用
  • orElseThrow(Supplier<? extends X> exceptionSupplier):与get()类似,不同的是可以自定义异常类型

收集器工具类Collectors

可在Streamcollect方法中使用

  • toCollection 转换成其他集合
  • maxBy/minBy/averagingInt/summingInt 转换成值
  • partitioningBy 数据二分
  • groupingBy 数据分多组
  • joining 字符串拼接(可支持自定义分隔符、前缀和后缀)
    注:menu.stream().map(Dish::getName).collect(joining());中当Dish对象实现了toString方法时,可以直接简写为menu.stream().collect(joining());
  • mapping 转换集合类型

并行化流

  • parallel: 将流并行化
  • sequential: 将流串行化

并行流底层使用了fork/join框架,因此能重复将数据结构对半分解的难易程度,决定了分解操作的快慢,如支持随机读取的数组并行化处理的性能最好,其次是TreeSetHashSet这样不易公平分解的数据类型,最差的是LinkedList这样长度未知的数据类型。

并行化数组操作

可以通过工具类Arrays进行,其主要方法有

  • copyOf 复制数组
  • parallelSetAll 使用Lambda表达式更新数组元素
  • parallelPrefix 任意给定一个函数,逐个将当前元素和之前的累计值进行函数操作
  • parallelSort 并行化对数组元素进行排序

相关文章

网友评论

    本文标题:JDK8中Stream及Optional学习笔记

    本文链接:https://www.haomeiwen.com/subject/gzfhlctx.html