天天看点

JDK1.8新特性---Stream流

一.流(Stream)到底是什么?

是数据渠道,用于操作数据源(集合、数组等)所生成元素

的序列。

“集合讲的是数据,流讲的是计算”

注意:

1.Stream自己不会存储元素。

2.Stream不会改变源对象。相反,他们会返回一个持有

新结果的Stream。

3.Stream操作是延迟执行的。这意味它们会等到需要

结果的时候执行。

二.Stream 的三个操作步骤

1.创建Stream

public class TestStreamAPI {
    //创建Stream
    @Test
    public void test1(){
        /*
        1.可以通过Collection 系列集合提供的Stream()
           或parallelStream(),Stream()产生的是串行流,
           parallelStream()产生的是并行流。
         */
        List<String> list=new ArrayList<>();
        Stream<String> stream = list.stream();

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

        //3.通过Stream 类中的静态方法of()
        Stream<String> stream2 = Stream.of("a", "b", "c");

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

}
           

2.中间操作

public class TestStreamAPI2 {
    private List<Employee> employees=Arrays.asList(
            new Employee("张三",18,999.99),
            new Employee("李四",38,555.55),
            new Employee("王五",50,444.44),
            new Employee("赵六",16,333.33),
            new Employee("田七",8,222.22),
            new Employee("田七",8,222.22),
            new Employee("田七",8,222.22)

    );
    //中间操作
    /*
     * 筛选与切片
     * filter----接收Lambda,从流中排除某些元素
     * limit---截断流,使其元素不超过给定数量
     * skip(n)---跳过,返回一个扔掉了前n个元素的流。若流中元素不满n个,则返回一个空流。与limit互补。
     * distinct---筛选,通过流所生成的hashcode()和equals()去除重复元素
     *
     * 排序
     * sorted()---自然排序(Comparable)
     * sorted(Comparator com)---定制排序(Comparator)
     *
     */
    //filter----接收Lambda,从流中排除某些元素
    @Test
    public void test1(){
        //中间操作,不会执行任何操作。
        Stream<Employee> stream = this.employees.stream()
                .filter((e) -> {
                            System.out.println("Stream API中间操作");
                            return e.getAge() > 35;
                        }
                );
        //终止操作,一次性执行全部内容,即“惰性求值”
        stream.forEach(System.out::println);
    }
    //内部迭代,迭代操作由StreamAPI完成
    @Test
    public void test2(){
        //这是外部迭代
        Iterator<Employee> iterator = this.employees.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

    //limit---截断流,使其元素不超过给定数量,注意在截断了指定的元素后就不会往下迭代了
    @Test
    public void test3() {
        this.employees.stream()
                .filter((e) ->
                {
                    System.out.println("短路操作");
                    return e.getSalary() > 200;

                })
                .limit(2)
                .forEach(System.out::println);
    }

    //skip(n)---跳过,返回一个扔掉了前n个元素的流。若流中元素不满n个,则返回一个空流。与limit互补。
    @Test
    public void test4(){
        this.employees.stream()
                .filter((e)->e.getSalary()>200)
                .skip(2)
                .forEach(System.out::println);
    }

    //distinct---筛选,通过流所生成的hashcode()和equals()去除重复元素
    @Test
    public void test5(){
        this.employees.stream()
                .filter((e)->e.getSalary()>200)
                .skip(2)
                .distinct()
                .forEach(System.out::println);
    }

    /*
     * sorted()---自然排序(Comparable)
     * sorted(Comparator com)---定制排序(Comparator)
     */
    @Test
    public void test6(){
        List<String> list=Arrays.asList("b","a","c");
        list.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("**************");
        this.employees.stream()
                .sorted((e1,e2)->{
                    if(e1.getAge().equals(e2.getAge())){
                        return e1.getSalary().compareTo(e2.getSalary());
                    }
                    return e1.getAge().compareTo(e2.getAge());
                })
                .forEach(System.out::println);
    }
    
}
           
public class TestStreamAPI3 {
    private List<Employee> employees=Arrays.asList(
            new Employee("张三",18,999.99),
            new Employee("李四",38,555.55),
            new Employee("王五",50,444.44),
            new Employee("赵六",16,333.33),
            new Employee("田七",8,222.22),
            new Employee("田七",8,222.22),
            new Employee("田七",8,222.22)

    );
    /*
     * 映射
     * map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其
     *      映射成一个新的元素。
     * flatMap---接收一个函数作为参数,流中的每个值都换成另一个流,然后把所有流连城一个流
     */
    @Test
    public void test1(){
        Arrays.stream(new String[]{"aa","bb","cc"})
                .map((str)->str.toUpperCase())
                .forEach(System.out::println);

        System.out.println("******************");
        this.employees.stream()
                .map(Employee::getName)
                .distinct()
                .forEach(System.out::println);

        System.out.println("******************");
        Stream<Stream<Character>> stream = Arrays.stream(new String[]{"aa", "bb", "cc"})
                .map(TestStreamAPI3::filterCharacter);
        stream.forEach((s)->s.forEach(System.out::println));

        System.out.println("******************");
        //flatMap
        Arrays.stream(new String[]{"aa", "bb", "cc"})
                .flatMap(TestStreamAPI3::filterCharacter)
                .forEach(System.out::println);

    }

    public static Stream<Character> filterCharacter(String str){
        List<Character> characterList=new ArrayList<>();
        for (Character character : str.toCharArray()) {
            characterList.add(character);
        }
        return characterList.stream();
    }
}
           

3.终止操作(终端操作)

public class TestStreamAPI4 {
    /*
     * 查找与匹配
     * allMatch-检查是否匹配所有元素
     * anyMatch-检查是否至少匹配一个元素
     * noneMatch-检查是否没有匹配
     * findFirst-返回第一个元素
     * findAny-返回当前流中中的任意元素
     * count-返回流中元素的总个数
     * max-返回流中最大值
     * min-返回流中最小值
     */
    private List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 999.99, Employee.Status.FREE),
            new Employee("李四", 38, 555.55, Employee.Status.BUSY),
            new Employee("王五", 50, 444.44, Employee.Status.VOCATION),
            new Employee("赵六", 16, 333.33, Employee.Status.FREE),
            new Employee("田七", 8, 222.22, Employee.Status.BUSY)

    );

    @Test
    public void test1() {
        boolean flag = employees.stream()
                .anyMatch(e -> e.getStatus() == Employee.Status.BUSY);
        System.out.println(flag);

        flag = employees.stream().
                allMatch(e -> e.getStatus() == Employee.Status.BUSY);
        System.out.println(flag);

        flag = employees.stream().
                noneMatch(e -> e.getStatus() == Employee.Status.BUSY);
        System.out.println(flag);

        Optional<Employee> op = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary))
                .findFirst();
        System.out.println(op.get());

        Optional<Employee> any = employees.parallelStream()
                .filter((e) -> e.getStatus() == Employee.Status.FREE)
                .findAny();
        System.out.println(any.get());

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

        Optional<Employee> max = employees.stream()
                .max(Comparator.comparingDouble(Employee::getSalary));
        System.out.println(max.get());

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


    }

    /*
     * 归约
     * reduce(T identity ,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来,得到一个值
     */
    @Test
    public void test01() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        Integer reduce = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(reduce);
        System.out.println("**************");
        Optional<Double> reduce1 = employees.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(reduce1.get());
    }

    /*
     * 收集
     * collection-将流转为其它形式。接收一个collection接口实现,用于Stream中元素做汇总的方法
     */
    @Test
    public void test03() {
        List<String> collect = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        System.out.println(collect);
        System.out.println("***********************");
        HashSet<String> hashSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(hashSet);
        System.out.println("******************");
        //总数
        Long value = employees.stream()
                .collect(Collectors.counting());
        System.out.println("总数"+value);
        //平均值
        Double aDouble = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println("工涨平均值:"+aDouble);
        //总和
        Double aDouble1 = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println("工涨总和:"+aDouble1);
        //最大值
        Optional<Employee> collect1 = employees.stream()
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println("工涨最大值:"+collect1.get());
        //分组
        Map<Employee.Status, List<Employee>> collect2 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(collect2);
        //多级分组
        Map<Employee.Status, Map<String, List<Employee>>> collect3 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy(
                        (e) -> {
                            if (((Employee) e).getAge() <= 35) {
                                return "青年";
                            }
                            if (((Employee) e).getAge() <= 50) {
                                return "中年";
                            }
                            return "老年";
                        }
                )));
        System.out.println(collect3);
        //分片
        Map<Boolean, List<Employee>> collect4 = employees.stream()
                .collect(Collectors.partitioningBy(e -> e.getSalary() > 800));
        System.out.println(collect4);
        System.out.println("********************");
        DoubleSummaryStatistics collect5 = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(collect5.getCount());
        System.out.println("**********************");
        //连接字符串
        String collect6 = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",", "prefix", "suffix"));
        System.out.println(collect6);
    }
}