Stream流的应用

Stream 流:对数据进行操作

数据源:集合、数组

一系列流水线式中间操作

产生新的流,不改变原有流。

流是什么?

是数据渠道,用于操作数据源所生成的元素序列。

集合讲的是数据,流讲的是计算!

注意:

  1. Stream自己不会存储元素
  2. Stream不会改变原对象
  3. Stream操作是延时的

操作:

  • 创建Stream
  • 中间操作
  • 终止操作(终端操作)

一、创建流的几种方式:

  1. 通过Collection系列集合提供的Stream()或parallelStream()

  2. 通过Arrays中的静态方法stream()获取数组流

  3. 通过Stream类中的静态方法of()

  4. 创建无限流

public class StreamAPITest01 {
    //创建Stream

    public static void main(String[] args){
        //1、通过Collection系列集合提供的Stream()或parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
        Stream<String> stringStream = list.parallelStream();

        //2.通过Arrays中的静态方法stream()获取数组流
        Integer[] i1 = new Integer[10];
        Stream<Integer> stream2 = Arrays.stream(i1);

        //3.通过Stream类中的静态方法of()
        Stream<String> stream3 = Stream.of("aa", "bb", "cc");

        //4创建无限流
        //迭代
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        stream4.limit(10)
                .forEach(System.out::println);
        //生成
        Stream.generate(()->Math.random())
                .limit(10)
                .forEach(System.out::println);

    }
}

二、流的中间操作

  1. 筛选与切片
    • filter--接收Lambda,从流中排除默写元素
  • limit--截断流,使其元素不超过给定数量
    • skip(n)--跳过元素,扔掉前n个元素的流,数量不足返回空流
  • distinct--筛选,通流所生成的hashCode()和equals()去除重复元素
     public class StreamAPITest02 {
         public static void main(String[] args) {
             //中间操作
             /*
                 筛选与切片
                 filter--接收Lambda,从流中排除默写元素
                 limit--截断流,使其元素不超过给定数量
                 skip(n)--跳过元素,扔掉前n个元素的流,数量不足返回空流
                 distinct--筛选,通流所生成的hashCode()和equals()去除重复元素
     
              */
             List<Employee> employees = Arrays.asList(
                     new Employee("张三", 18, 9999.99),
                     new Employee("李四", 58, 5555),
                     new Employee("王五", 26, 333.33),
                     new Employee("赵六", 36, 666.66),
                     new Employee("田七", 12, 888.88)
             );
     
             //filter的使用
             //内部迭代 迭代由Streamle API完成
             Stream<Employee> stream = employees.stream()
                     .filter((e) -> {
                         System.out.println("Stream API 的中间操作!");
                         return e.age > 35;
                     });
             //在执行 以下终止操作后才会一次性全部处理,称为“惰性求值”
             stream.forEach(System.out::println);
     
             //外部迭代
             Iterator<Employee> it = employees.iterator();
             while (it.hasNext()) {
                 System.out.println(it.next());
             }
     
             //limit的使用
             employees.stream()
                     .filter((e) -> e.getMoney() > 5000)
                     .limit(2)
                     .forEach(System.out::println);
             
             //skip和distinct的使用
             employees.stream()
                     .filter((e) -> e.getMoney() > 5000)
                     .skip(2)
                     .distinct()
                     .forEach(System.out::println);
         }
     }
2.映射
  • map--接收Lambda,将元素转换成其他形式或提取信息
  • flatMap--接收一个函数作为参数,将流中每个值换成另一个流,然后把所有流连接成一个流
public class StreamAPITest03 {
    public static void main(String[] args) {
       /*
            映射
            map--接收Lambda,将元素转换成其他形式或提取信息
            flatMap--接收一个函数作为参数,将流中每个值换成另一个流,然后把所有流连接成一个流

         */
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99),
                new Employee("李四", 58, 5555),
                new Employee("王五", 26, 333.33),
                new Employee("赵六", 36, 666.66),
                new Employee("田七", 12, 888.88)
        );

        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        //map的使用
        list.stream()
                .map((str) -> str.toUpperCase())
                .forEach(System.out::println);
        System.out.println("----------------------------");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);

        Stream<Stream<Character>> streamStream = list.stream()
                .map(StreamAPITest03::filterCharacter);
        //流形式为:{{a,a,a},{b,b,b}}
        streamStream.forEach(stm -> {
            stm.forEach(System.out::println);
        });
        
        //flatMap的使用
        System.out.println("-----------------------------");
        Stream<Character> characterStream = list.stream()
                .flatMap(StreamAPITest03::filterCharacter);
        //流形式为:{a,a,a,b,b,b}
        characterStream.forEach(System.out::println);

        System.out.println("-------------------------------");


    }
    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (Character ch:str.toCharArray()){
            list.add(ch);
        }
        return list.stream();
    }
    
}
3.排序
  • sorted()--自然排序)(Comparable)
  • sorted(Comparator)--定制排序
public class StreamAPITest04 {
    public static void main(String[] args){
        /*
            sorted()--自然排序)(Comparable)
            sorted(Comparator)--定制排序
         */
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
        list.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("------------------------------");

        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99),
                new Employee("李四", 58, 5555),
                new Employee("王五", 26, 333.33),
                new Employee("赵六", 36, 666.66),
                new Employee("田七", 12, 888.88)
        );
        employees.stream()
                .sorted((e1,e2)->{
                    if (e1.getAge() == e2.getAge()) {
                        return e1.getName().compareTo(e2.getName());
                    }else {
                        return e1.getAge()-e2.getAge();
                    }
                })
                .forEach(System.out::println);

    }
}
4. 查找与匹配
  • allMatch--检查匹配所有 元素
  • anyMatch--检查是否至少匹配一个元素
  • noneMatch--检查是否没有匹配所有元素
  • findFirst--返回第一个元素
  • findAny -- 返回当前流中任意元素
  • count--返回流中元素个数
  • max--返回流中最大值
  • min--返回流中最小值
public class StreamAPITest05 {
    public static void main(String[] args){
       /*
        查找与匹配
        allMatch--检查匹配所有 元素
        anyMatch--检查是否至少匹配一个元素
        noneMatch--检查是否没有匹配所有元素
        findFirst--返回第一个元素
        findAny -- 返回当前流中任意元素
        count--返回流中元素个数
        max--返回流中最大值
        min--返回流中最小值
        */
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
                new Employee("李四", 58, 5555, Employee.Status.FTEE),
                new Employee("王五", 26, 333.33, Employee.Status.BUSY),
                new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
                new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
        );
        //是否匹配所有元素
        boolean b1 = employees.stream()
                .allMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        //至少匹配一个
        boolean b2 = employees.stream()
                .anyMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        //没有匹配所有元素 有匹配的元素
        boolean b3 = employees.stream()
                .noneMatch(e -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b3);
        //返回第一个
        Optional<Employee> op = employees.stream()    //提供op.orElse(other),如果对象为空则用other代替,避免空指针
                .sorted((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()))
                .findFirst();//值有可能为空  封装到Optional中
        System.out.println(op.get());
        //返回任意一个
        Optional<Employee> any = employees.stream()
                .filter(e -> e.getStatus().equals(Employee.Status.FTEE))
                .findAny();
        System.out.println(any.get());
        //个数
        long count = employees.stream()
                .count();
        System.out.println(count);
        //最大值
        Optional<Employee> max = employees.stream()
                .max((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()));
        System.out.println(max.get());
        //最小值
        Optional<Employee> min = employees.stream()
                .min((e1, e2) -> (int) (e1.getMoney() - e2.getMoney()));
        System.out.println(min.get());
        
    }
}

三、流的终止操作

1.归约与收集
  • 归约:reduce(T identity,BinaryOperator) reduce(BinaryOperator)

    --可以将流中元素反复结合起来得到一个值

  • 收集collect

    --将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

public class StreamAPITest06 {
    public static void main(String[] args) {
        //归约:reduce(T identity,BinaryOperator)/deduce(BinaryOperator
        //--可以将流中元素反复结合起来得到一个值
        List<Integer> list = Arrays.asList(1,2,4,5,6,7,8);
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);

        System.out.println("------------------------------------------");
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
                new Employee("李四", 58, 5555, Employee.Status.FTEE),
                new Employee("王五", 26, 333.33, Employee.Status.BUSY),
                new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
                new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
        );
        //可能为空返回Optional
        Optional<Double> op = employees.stream()
                .map(Employee::getMoney)
                .reduce(Double::sum);
        System.out.println(op.get());

        //收集
        //collect--将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
        employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList())
                .forEach(System.out::println);

        System.out.println("--------------------------------------------");
        Set<String> set = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());

        System.out.println("-----------------------------------------------");
        HashSet<String> hashSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));

        System.out.println("------------------------------------------------");
        //总数
        Long count = employees.stream()
                .collect(Collectors.counting());
        System.out.println(count);

        System.out.println("-------------------------------------");
        //平均值
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getMoney));
        System.out.println(avg);

        System.out.println("-------------------------------------");
        //工资总和
        Double sum1 = employees.stream()
                .collect(Collectors.summingDouble(Employee::getMoney));
        System.out.println(sum1);

        System.out.println("-------------------------------------");
        //最大值
        Optional<Employee> max = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getMoney(), e2.getMoney())));
        System.out.println(max.get());

        System.out.println("-------------------------------------");
        //最小值
        Optional<Double> min = employees.stream()
                .map(Employee::getMoney)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min);



    }
}
  • 收集的应用--分组/多级分组
public class StreamAPITest07 {
    public static void main(String[] args) {
        //分组
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
                new Employee("李四", 58, 5555, Employee.Status.FTEE),
                new Employee("王五", 26, 333.33, Employee.Status.BUSY),
                new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
                new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
        );
        //
        Map<Employee.Status, List<Employee>> map = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);

        //多级分组
        Map<Employee.Status, Map<String, List<Employee>>> map1 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(e -> {
                    if (((Employee) e).getAge() <= 35) {
                        return "青年";
                    } else if (e.getAge() <= 50) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));
        System.out.println(map1);

    }
}
  • 收集的应用--分区
public class StreamAPITest08 {
    public static void main(String[] args) {
        //分区
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 18, 9999.99, Employee.Status.BUSY),
                new Employee("李四", 58, 5555, Employee.Status.FTEE),
                new Employee("王五", 26, 333.33, Employee.Status.BUSY),
                new Employee("赵六", 36, 666.66, Employee.Status.FTEE),
                new Employee("田七", 12, 888.88, Employee.Status.VOCATION)
        );
        Map<Boolean, List<Employee>> map1 = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getMoney() > 8000));
        System.out.println(map1);

        DoubleSummaryStatistics dss = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getMoney));
        System.out.println(dss.getAverage());
        System.out.println(dss.getCount());
        System.out.println(dss.getMax());
        System.out.println(dss.getMin());
        System.out.println(dss.getSum());

        String str = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",","===","==="));
        System.out.println(str);
    }
}
posted @ 2021-04-20 19:45  愿半生代码如一生好友  阅读(169)  评论(0)    收藏  举报