• JDK1.8新特性(一):stream


    一.什么是stream?

    1.概述

    Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

    这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

    元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。

    简单描述一下大概是这样:

    二. 举个例子?

    现在有一个字符串集合,我们需要过滤掉集合里头长度小于2的字符串:

    public static void main( String[] args ) {
        List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
        List<String> stringList = new ArrayList<>();
        for (String str : strings){
            //如果长度大于2
            if (str.length() >= 2){
                //将字符串添加至新集合
                stringList.add(str);
            }
        }
        strings = stringList;
    }
    

    如果使用stream实现一模一样的效果:

    public static void main( String[] args ) {
        List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
        //通过stream操作集合
        strings = strings.stream()
            //去掉长度小于2的字符串
            .filter(s -> s.length() >= 2)
            //转回集合
            .collect(Collectors.toList());
    }
    

    可见,使用streamAPI可以轻松写出更高效,更简洁,可读性更强的代码

    三. 如何使用stream?

    简单的说,分两步:生成流,操作流

    1. 生成流

    Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, 不支持Map

    1.1 Collection接口的stream()或parallelStream()方法

    //将Set或List集合直接转换为stream对象
    List<Person> personList = new ArrayList<>();
    Set<Person> set = new HashSet<>();
    
    Stream<Person> personStream1 = personList.stream();//生成串行流
    Stream<Person> personStream2 = set.parallelStream();//生成并行流
    

    1.2 Stream.of(),Arrays.stream,Stream.empty()方法

    String[] strArr = {"a","a","a","a","a","a"};
    
    //Stream.empty()
    Stream<Integer> integerStream = Stream.empty();
    
    //Stream.of() (方法内部调用的还是Arrays.stream)
    Stream<String> stringStream = Stream.of(strArr);
    
    //Arrays.stream
    Stream<String> stringStream2 = Arrays.stream(strArr);
    

    1.3 Stream.concat()方法

    //已有的对象
    Stream<Integer> integerStream = Stream.empty();
    Stream<String> stringStream = Stream.of(strArr);
    Stream<String> stringStream2 = Arrays.stream(strArr);
    
    //合并两个流
    Stream conStream1 = Stream.concat(stringStream,integerStream);
    Stream conStream2 = Stream.concat(stringStream,stringStream2);
    

    1.4 静态的Files.lines(path)

    File file = new File("D://test.txt");
    Stream<String> lines = Files.lines(file);
    

    2. 操作流

    Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以在后头跟上其他中间操作

    //接下来的示例代码基于此集合
    List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
    

    2.1 filter(Predicate:将结果为false的元素过滤掉

    //去掉长度小于2的字符串
    strings = strings.stream()
        .filter(s -> s.length() >= 2)
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings
    [ab, bc, cd, abcd, jkl]
    

    2.2 map(fun):转换元素的值,可以引用方法或者直接用lambda表达式

    strings = strings.stream()
        //为每个字符串加上“???”
        .map(s -> s += "???")
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings
    [ab???, ???, bc???, cd???, abcd???, ???, jkl???]
    

    2.3 limit(n):保留前n个元素

    strings = strings.stream()
        //保留前3个
        .limit(3)
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings
    [ab, , bc]
    

    2.4 skip(n):跳过前n个元素

    strings = strings.stream()
        //跳过前2个
        .skip(2)
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings
    [bc, cd, abcd, , jkl]
    

    2.5 distinct():剔除重复元素

    strings = strings.stream()
        //过滤重复元素
        .distinct()
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings(过滤掉了一个空字符串)
    [ab, , bc, cd, abcd, jkl]
    

    2.6 sorted():通过Comparable对元素排序

    strings = strings.stream()
        //按字符串长度排序
        .sorted(
            //比较字符串长度
            Comparator.comparing(s -> s.length())
    	)
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings(过滤掉了一个空字符串)
    [, , ab, bc, cd, jkl, abcd]
    

    2.7 peek(fun):流不变,但会把每个元素传入fun执行,可以用作调试

    strings = strings.stream()
        //为字符串增加“???”
        .peek(s -> s += "???")
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(strings);
    
    //打印strings,和map对比,实际并没有改变集合
    [ab, , bc, cd, abcd, , jkl]
    

    2.8 flatMap(fun):若元素是流,将流摊平为正常元素,再进行元素转换

    //将具有多重嵌套结构的集合扁平化
    
    //获取一个两重集合
    List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
    List<String> strings2 = Arrays.asList("asd", "", "bzxasdc", "cddsdsd", "adsdsg","", "jvcbl");
    List<List<String>> lists = new ArrayList<>();
    lists.add(strings);
    lists.add(strings2);
    
    //获取将两重集合压成一层
    List<String> stringList = lists.stream()
        //将两重集合的子元素,即集合strings和strings2转成流再平摊
        .flatMap(Collection::stream)
        //返回集合
        .collect(Collectors.toList());
    
    System.out.println(stringList);
    
    //打印stringList
    [ab, , bc, cd, abcd, , jkl, asd, , bzxasdc, cddsdsd, adsdsg, , jvcbl]
    

    2.9 anyMatch(fun),allMatch(fun):判断流中的元素是否匹配 【最终操作】

    //allMatch
    Boolean isAllMatch = strings.stream()
        //判断元素中是否有匹配“ab”的字符串,返回true或fals
        //判断元素中的字符串是否都与“ab”匹配,返回true或fals
        .allMatch(str -> str.equals("ab"));
    
    System.out.println(isMatch);
    
    //anyMatch
    Boolean isAnyMatch = strings.stream()
        //判断元素中是否有匹配“ab”的字符串,返回true或fals
        .anyMatch(str -> str.equals("ab"));
    
    System.out.println("isAnyMatch:" + isAnyMatch);
    System.out.println("isAllMatch:" + isAllMatch);
    
    //打印结果
    isAnyMatch:true
    isAllMatch:false
    

    2.10 forEach(fun): 迭代流中的每个数据 【最终操作】

    strings.stream()
        //遍历每一个元素
        .forEach(s -> System.out.print(s + "; "));
    

    2.11 collect():返回结果集 【最终操作】

    strings = strings.stream()
        //返回集合
        .collect(Collectors.toList());
    

    四. 使用IntSummaryStatistics类处理数据

    1. IntSummaryStatistics类

    IntSummaryStatistics类,在 java8中配合Stream使用,是用于收集统计信息(例如计数,最小值,最大值,总和和*平均值)的状态对象。

    这个类长这样:

    public class IntSummaryStatistics implements IntConsumer {
        private long count;
        private long sum;
        private int min = Integer.MAX_VALUE;
        private int max = Integer.MIN_VALUE;
        
        public IntSummaryStatistics() { }
    
        @Override
        public void accept(int value) {
            ++count;
            sum += value;
            min = Math.min(min, value);
            max = Math.max(max, value);
        }
    
        public void combine(IntSummaryStatistics other) {
            count += other.count;
            sum += other.sum;
            min = Math.min(min, other.min);
            max = Math.max(max, other.max);
        }
    
        public final long getCount() {
            return count;
        }
    
    
        public final long getSum() {
            return sum;
        }
    
        public final int getMin() {
            return min;
        }
    
        public final int getMax() {
            return max;
        }
    
        public final double getAverage() {
            return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
        }
    
        @Override
        public String toString() {
            return String.format(
                "%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
                this.getClass().getSimpleName(),
                getCount(),
                getSum(),
                getMin(),
                getAverage(),
                getMax());
        }
    }
    
    

    2.使用

    这个类的理解起来很简单,内部有这几个方法:

    2.1 获取总条数:getCount(),

    2.2 获取和:getSum(),

    2.3 获取最小值:getMin(),

    2.4 获取最大值:getMax(),

    2.5 获取平均值:getAverage()

    示例如下:

    public static void main( String[] args ) {
        List<Integer> integerList = Arrays.asList(3, 4, 22, 31, 75, 32, 54);
    
        IntSummaryStatistics sta = integerList
            .stream()
            //将元素映射为对应的数据类型(int,double,long)
            .mapToInt(i -> i)
            //转换为summaryStatistics类
            .summaryStatistics();
    
        System.out.println("总共有 : "+ sta.getCount());
        System.out.println("列表中最大的数 : " + sta.getMax());
        System.out.println("列表中最小的数 : " + sta.getMin());
        System.out.println("所有数之和 : " + sta.getSum());
        System.out.println("平均数 : " + sta.getAverage());
    }
    
    //打印结果
    总共有 : 7
    列表中最大的数 : 75
    列表中最小的数 : 3
    所有数之和 : 221
    平均数 : 31.571428571428573
    
    
  • 相关阅读:
    CentOS 6.4 x64 zabbix 2.2.2 编译安装
    Monitorix 监控 安装配置
    CentOS 6.4 x64 Percona-Server-5.6.15 源码安装
    CentOS 6.4 x64 安装 配置 Redmine 2.4.1
    ActiviMQ的基本使用
    Java内存 模型理解
    线程池的两种创建方式及区别
    线程创建的三种方式及区别
    Spring cloud 之Ribbon(二)负载均衡原理
    Spring cloud 之Ribbon(一)基本使用
  • 原文地址:https://www.cnblogs.com/Createsequence/p/11967561.html
Copyright © 2020-2023  润新知