Stream:不同于IO流,Stream流是数据渠道,用于操作数据源(集合/数组)所生成的元素序列

三大特性:

1.Stream 不会存储元素

2.Stream 不会改变源对象,相反,会返回一个持有结果的新Stream

3.Stream 操作是延时的,遇到终止操作才会一次性全部执行

 

1.流的创建

  //创建
    @Test
    public void test1() {
        //1.Collection系列集合提供的stream()串行流 或 paralleStream()并行流
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();

        //2.Arrays中静态方法Stream()获取数组流
        Employee[] employees = new Employee[10];
        Stream<Employee> stream2 = Arrays.stream(employees);

        //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);

        //5.
        Stream.generate(() -> Math.random())
                .forEach(System.out::println);
    }

 

2.流的操作

 @Test
    public void test2() {
        //filter
        employees.stream().filter((e) -> e.getAge() > 18).forEach((employee -> System.out.println(employee)));

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

        Stream<Employee> stream = employees.stream()
                .filter((e) -> {
                    System.out.println("这里是中间操作!");
                    return e.getAge() > 19;
                });
        //终止操作:一次性执行全部
        stream.forEach(System.out::println);

//  employees.stream().filter((e) -> e.getAge() > 25).forEach(System.out::println);

    }


    @Test
    public void test3() {
        //找到匹配条件的 不会继续迭代  类似 && ||
        employees.stream()
                .filter((e -> {
                    System.out.println("短路");
                    return e.getSalary() > 5000;
                }))
                .limit(1)
                .forEach(e -> System.out.println(e));
    }

    @Test
    public void test4() {
        //distinct 通过hashCode() 和 equals去重
        //要想达到效果,需要重写employee中的hashCode方法或者equals方法
        employees.stream()
                .filter((e -> {
//                    System.out.println("短路");
                    return e.getSalary() > 5000;
                }))
                .distinct()
                .forEach(e -> System.out.println(e));

    }

    @Test
    public void test5() {
        // distinct
        employees.stream()
                .filter((e -> {
//                    System.out.println("短路");
                    return e.getSalary() > 5000;
                }))
                .skip(2)
                .forEach(e -> System.out.println(e));

    }


    /**
     * 映射:
     * map:接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个参数上,并将其映射成一个新的元素
     * flatMap:接收一个函数作为参数,将流中的每一个值都转换成另一个流,然后把所有的流连接成一个流
     */
    @Test
    public void test6() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        list.stream()
                //从"aaa", "bbb", "ccc", "ddd", "eee"提取出每一个元素 将map中的函数应用于每一个参数上
                .map(str -> str.toUpperCase())
                .forEach(System.out::println);

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

        employees.stream()
                //对employee集合中的每一参数 都做employee.getName()操作
                .map(employee -> employee.getName())
                .forEach(System.out::println);
    }


@Test
public void test7() { List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee"); Stream<Stream<Character>> stream = list.stream() .map(TestStream1::filterCharacter); stream.forEach(sm->sm.forEach(System.out::println)); System.out.println("---------------------------------------------"); Stream<Character> characterStream = list.stream().flatMap(TestStream1::filterCharacter); characterStream.forEach(System.out::println); } public static Stream<Character> filterCharacter(String str) { List list = new ArrayList(); //Character -> char的包装类型 for (Character ch : str.toCharArray()) { list.add(ch); } return list.stream(); }

 

  @Test
    public void test8() {
        //sort

        employees.stream()
                .sorted((e1, e2) -> {
                    if (e1.getAge() == e2.getAge()) {
                        //年龄相同按照姓名排序
                        return e1.getName().compareTo(e2.getName());
                    }else {
                        return ((Integer)e1.getAge()).compareTo((Integer)e2.getAge());
                    }
                }).forEach(System.out::println);
    }

 

 

 @Test
    /**
     * 查找于匹配
     *
     */
    public void test1() {
        //需求:找出salary最低的员工

        Optional<Double> op = employees.stream()
                .map(Employee::getSalary)
                .min(Double::compareTo);
        System.out.println(op.get());
    }


    /**
     * 归约
     * reduce:将流中的元素反复结合起来,得到一个值
     */

    @Test
    public void test2() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer reduce1 = list.stream()
                //reduce 第一个参数 起始值,即将0赋给x 1赋给y 运算后将结果1赋给x 如此循环
                .reduce(0, (x, y) -> x + y);
        System.out.println(reduce1);

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

        //计算salary总和
        Optional<Double> reduce2 = employees.stream().map(Employee::getSalary)
                .reduce(Double::sum);
//                .reduce((x, y) -> x + y);
        System.out.println(reduce2.get());

    }


    //collect:将流转换为其他形式,接收一个Collection接口的实现,用于给Stream中元素做汇总
    @Test
    //把员工名收集
    public void test3() {

        List<String> list1 = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());

        list1.forEach(System.out::println);

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

        //可以收集到set集合中去重
        Set<String> list2 = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());

        list2.forEach(System.out::println);

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

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

        hashSet.forEach(System.out::println);

    }


    @Test
    public void test4() {
        //返回集合总数
        Long num = employees.stream().collect(Collectors.counting());
        System.out.println(num);

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

        System.out.println(employees.stream().count());

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

        //平均值
        System.out.println(employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary)));
    }


    @Test
    public void test5() {

        //总和
        System.out.println(employees.stream().collect(Collectors.summingDouble(Employee::getSalary)));
        //工资最大值员工
        System.out.println(employees.stream().collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))));

        //最小值
        System.out.println(employees.stream()
                .map(Employee::getSalary)
//                .map(e -> e.getSalary())
                .collect(Collectors.minBy(Double::compare)));
    }
 //分组操作
    @Test
    public void test6() {
        //根据Status分组
        Map<Status, List<Employee>> collect1 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
    }

    //收集一个组函数对象 之后可以做分组处理
    @Test
    public void test7() {

        //根据Status分组
        DoubleSummaryStatistics dss = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));

        System.out.println(dss.getAverage());//8000.0
        System.out.println(dss.getCount());//7
        System.out.println(dss.getMax());//11000.0
    }

    //将收集的所有内容连接
    @Test
    public void test8() {
        //根据Status分组
        String s = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",","===","==="));

        System.out.println(s);//===Mike,Yan,Lee,Rose,Sk,Sk,Sk===

    }