美文网首页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