• java8新特性(四)_Stream详解


    之前写过一篇用stream处理map的文章,但是对stream没有一个整体的认识,这次结合并发编程网和ibm中介绍stream的文章进行一个总结,我会着重写对list的处理,毕竟实际工作中大家每天进行使用

    Stream简单介绍

    定义

    • A sequence of elements supporting sequential and parallel aggregate operations.

    • 支持顺序并行聚合操作的元素序列

    看看大神们怎么解读的

    大家可以把Stream当成一个高级版本的Iterator。原始版本的Iterator,用户只能一个一个的遍历元素并对其执行某些操作;高级版本的Stream,用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,具体这些操作如何应用到每个元素上,就给Stream就好了

    简单demo

    写一个过滤null的简单功能
        public static void main(String[] args) {
    
            List arrys = Arrays.asList(1, null, 3, 4);
            arrys.forEach(System.out::print);
            System.out.println();
            arrys = (List) arrys.stream()
                    .filter(num -> num != null)
                    .collect(Collectors.toList());
            arrys.forEach(System.out::print);
    
        }
    

    执行结果

    1null34
    134
    
    解析代码


    1、 创建Stream;
    2、 转换Stream(处理数据),每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);
    3、 对Stream进行聚合(Reduce)操作,获取想要的结果;

    创建Stream

    最常用的创建Stream有两种途径:

    • 通过Stream接口的静态工厂方法
    • 通过Collection接口的默认方法–stream(),把一个Collection对象转换成Stream(之前写的文章对于map的处理就是基于这个)
    // 1. Individual values
    Stream stream = Stream.of("a", "b", "c");
    // 2. Arrays
    String [] strArray = new String[] {"a", "b", "c"};
    stream = Stream.of(strArray);
    stream = Arrays.stream(strArray);
    // 3. Collections(实际工作中经常用到)
    List<String> list = Arrays.asList(strArray);
    stream = list.stream();
    

    转换Stream方法详解

    这里其实是大家常用到的,着重讲解这里,这里的图片来自并发编程网,不得不佩服,程序写的好,画图也比我画的好

    distinct

    distinct: 对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法),新生成的Stream中没有重复的元素;

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            list = list.stream()
                    .distinct()
                    .collect(Collectors.toList());
            list.forEach(System.out::print);
    
        }
    

    结果

    java---java---erlang---lua---lua---
    java---erlang---lua---
    

    filter

    filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            list = list.stream()
                    .filter(e -> e.length() > 7)
                    .collect(Collectors.toList());
            list.forEach(System.out::print);
    
        }
    

    结果

    java---java---erlang---lua---lua---
    erlang---
    

    map

    map:它的作用就是把 input Stream 的每一个元素,映射成 output Stream 的另外一个元素。

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            list = list.stream()
                    .map(String::toUpperCase)
                    .collect(Collectors.toList());
            list.forEach(System.out::print);
    
        }
    

    结果

    java---java---erlang---lua---lua---
    JAVA---JAVA---ERLANG---LUA---LUA---
    

    limit

    limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            list = list.stream()
                    .limit(3)
                    .collect(Collectors.toList());
            list.forEach(System.out::print);
    
        }
    

    结果

    java---java---erlang---lua---lua---
    java---java---erlang---
    

    skip

    skip:返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            list = list.stream()
                    .skip(3)
                    .collect(Collectors.toList());
            list.forEach(System.out::print);
    
        }
    

    结果

    java---java---erlang---lua---lua---
    lua---lua---
    

    findFirst

    findFirst:它总是返回 Stream 的第一个元素,或者空。这里比较重点的是它的返回值类型:Optional

    示意图

    代码演示
        public static void main(String[] args) {
    
            List<String> list = Arrays.asList("java---", "java---", "erlang---", "lua---", "lua---");
            list.forEach(System.out::print);
            System.out.println();
            Optional<String> first = list.stream()
                    .findFirst();
    
            System.out.println(first.get());
    
        }
    

    结果

    java---java---erlang---lua---lua---
    java---
    

    总结

    当然,还有很多方法,这里不一一介绍,现实工作中使用常常结合起来

    比如这段代码就是之前文章 过滤map 中 null值和空串的例子

    public static Map<String, Object> parseMapForFilterByOptional(Map<String, Object> map) {
    
            return Optional.ofNullable(map).map(
                    (v) -> {
                        Map params = v.entrySet().stream()
                                .filter((e) -> checkValue(e.getValue()))
                                .collect(Collectors.toMap(
                                        (e) -> (String) e.getKey(),
                                        (e) -> e.getValue()
                                ));
    
                        return params;
                    }
            ).orElse(null);
        }
    

    总之,Stream 的特性可以归纳为:

    不是数据结构

    • 它没有内部存储,它只是用操作管道从 source(数据结构、数组、generator function、IO channel)抓取数据。
    • 它也绝不修改自己所封装的底层数据结构的数据。例如 Stream 的 filter 操作会产生一个不包含被过滤元素的新 Stream,而不是从 source 删除那些元素。
    • 所有 Stream 的操作必须以 lambda 表达式为参数

    参考文章
    -[1.]https://ifeve.com/stream/
    -[2.]https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

  • 相关阅读:
    ECS内网穿透
    设置服务器ssh会话时间
    VScode插件
    Linux拷贝U盘文件(命令行)
    打开IDM下载视频时弹出防火墙阻止下载,解决方案
    如何将jmeter.bat命令文件固定到任务栏
    jmeter安装教程
    安装JDK8.0(JDK1.8) & 环境变量配置 & idea中配置java路径
    教你不用任何第三方软件实现任务栏居中
    [Unity优化]gc03:代码优化
  • 原文地址:https://www.cnblogs.com/zhenghengbin/p/9500822.html
Copyright © 2020-2023  润新知