Java8中的Stream API

前言

Java8中有二个最为重要的改变。第一个是Lambda 表达式,另一个则是Strean API(Java.util.stream.*)Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似与使用SQL执行的数据库查询。也可以使用Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

什么是Stream(流)?

是数据的渠道,用于操作数据源(集合、数组等)所生成的元素序列。(集合讲的是数据,流讲的是计算)

注意:
1.Stream 自己不会存储元素
2.Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
3.Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

Stream 操作的三个步骤

1.创建Stream:一个数据源(集合,数组),获取一个流

 //1.创建Stream
    @Test
    public void test1(){
    
    
        //1.可以通过Collection 系列的集合提供的Stream() 或 parallelStream()
        List<String> list = new ArrayList<>();
        list.add("你好");
        Stream<String> stream1 = list.stream();

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

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

        //4.创建无限流
        //迭代,取前五个
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
                stream4.limit(5).forEach(System.out::println);

        //生成无数随机,取前5
        Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
    }

2.中间操作(一个中间操作链,对数据源的数据进行处理)

 /**
     * 筛选与切片
     *
     * filter --接收Lambda,从流中排除某些元素
     * limit--截断流,使元素不超过给定数量
     * skip(n) -- 跳过元素,返回一个扔掉了前n个元素的流。若流中元素不满足n个,则返回一个空流。与limit(n)互补
     * distinct -- 筛选 ,通过流所生成的hashCode() 和 equals() 去除重复元素。
     */
    @Test
    public void test2(){
    
    
        List<User> users = Arrays.asList(
                new User(18, "张三", "手机"),
                new User(20, "李四", "面包"),
                new User(20, "赵武", "矿泉水"),
                new User(15, "球球", "鸡腿"),
                new User(16, "球球", "鸡腿")
        );
        //中间操作:不会执行任何操作
        System.out.println("----------------filter--接收Lambda,从流中排除某些元素-------------------");
        //单条件过滤
        Stream<User> userStream1 = users.stream().filter((e) -> e.getAge() > 18);
        //多条件过滤1
        Stream<User> userStream2 = users.stream().filter((e) -> e.getAge() > 18).filter((e) -> e.getShop().equals("面包"));
        //多条件过滤2
        Stream<User> userStream3 = users.stream().filter((e) -> e.getAge() > 18 && e.getShop().equals("面包"));
        //终止操作:全部执行操作
        userStream1.forEach(System.out::println);

        System.out.println("----------------limit--截断流,使元素不超过给定数量---------------------");
        Stream<User> userStream4 = users.stream().limit(3);
        userStream4.forEach(System.out::println);

        System.out.println("-------skip(n) --跳过元素,返回一个扔掉了前n个元素的流。若流中元素不满足n个,则返回一个空流。与limit(n)互补--------");
        Stream<User> userStream5 = users.stream().skip(3);
        userStream5.forEach(System.out::println);

        System.out.println("---------distinct -- 筛选 ,通过流所生成的hashCode() 和 equals() 去除重复元素。-----------");
        //如果需要指定去重中不需要那么多则把实体类中hashCode()和equals()方法中的参数去除即可
        //方法1
        Stream<User> userStream6 = users.stream().distinct();
        userStream6.forEach(System.out::println);

        System.out.println("----------------------方法2----------------------------");
        //方法2
        List<User> userStream7 = users.stream()
                .collect(
                        Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(e ->
                                        e.getShop() + e.getName()
                                                ))),
                                ArrayList::new
                        )
                );
        System.out.println(userStream7);


    }
    /**
     * 映射
     * map--接收Lambda,讲元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,
     * 并将其映射成一个新的元素。
     * flatMap -- 接收一个函数作为参数,将流中的每个值都被换成另一个流,然后把所有流连成一个流
     */
    @Test
    public void test3(){
    
    
        List<String> list = Arrays.asList("a","b","c");

        List<User> userList = Arrays.asList(
                new User(18, "张三", "手机"),
                new User(20, "李四", "面包"),
                new User(20, "赵武", "矿泉水"),
                new User(15, "球球", "鸡腿"),
                new User(16, "球球", "鸡腿")
        );
        
        list.stream().map((e) -> e.toUpperCase()).forEach(System.out::println);
        
        System.out.println("--------获取实体对象的某一个值--------");

        userList.stream().map(User::getShop).forEach(System.out::println);

    }
    /**
     * 排序
     * sorted() --自然排序
     * sorted(Comparator com) -- 定制排序
     */
    @Test
    public void test7(){
    
    
        List<String> list = Arrays.asList("c","a","g","b");
        list.stream().sorted().forEach(System.out::println);

        List<User> userList = Arrays.asList(
                new User(18, "张三", "手机"),
                new User(20, "李四", "面包"),
                new User(20, "赵武", "矿泉水"),
                new User(15, "球球", "鸡腿"),
                new User(16, "球球", "鸡腿")
        );
        userList.stream().sorted((e1,e2) -> {
    
    
            if(e1.getAge().equals(e2.getAge())){
    
    
                return e1.getName().compareTo(e2.getName());
            }else{
    
    
                return e1.getAge().compareTo(e2.getAge());
            }
        }).forEach(System.out::println);
    }

3.终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果

 /**
     * 查找与匹配
     * allMatch --检查是否匹配所有元素
     * anyMatch --检查是否至少匹配一个元素
     * noneMach --检查是否没有匹配所有元素
     * findFirst -- 返回第一个元素
     * findAny -- 返回当前流中的任意元素
     * count -- 返回流中元素的总个数
     * max -- 返回流中的最大值
     * min -- 返回流中的最小值
     */
    @Test
    public void test8(){
    
    
        List<User> userList = Arrays.asList(
                new User(18, "张三", "手机", User.Status.BUSY),
                new User(20, "李四", "面包",User.Status.VOCATION),
                new User(20, "赵武", "矿泉水",User.Status.BUSY),
                new User(15, "球球", "鸡腿",User.Status.FREE),
                new User(16, "球球", "鸡腿",User.Status.FREE)
        );
        System.out.println("------------allMatch检查是否匹配所有元素--------------");
        boolean y = userList.stream().allMatch((e)-> e.getStatus().equals(User.Status.BUSY));
        System.out.println(y);

        System.out.println("------------anyMatch检查是否至少匹配一个元素--------------");
        boolean y2 = userList.stream().anyMatch((e) -> e.getStatus().equals(User.Status.BUSY));
        System.out.println(y2);

        System.out.println("------------ noneMach检查是否没有匹配所有元素--------------");
        boolean y3 = userList.stream().noneMatch((e) -> e.getStatus().equals(User.Status.BUSY));
        System.out.println(y3);

        System.out.println("------------ findFirst返回第一个元素--------------");
        Optional<User> op = userList.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).findFirst();
        System.out.println(op.get());

        System.out.println("------------ findAny返回当前流中的任意元素--------------");
        Optional<User> op2 = userList.stream().filter((e) -> e.getStatus().equals(User.Status.FREE)).findAny();
        System.out.println(op2);

        System.out.println("------------ count返回流中元素的总个数--------------");
        Long count = userList.stream().count();
        System.out.println(count);

        System.out.println("------------  max返回流中的最大值--------------");
        Optional<User> op3 = userList.stream().max((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge()));
        System.out.println(op3);

        System.out.println("------------ min返回流中的最小值--------------");
        Optional<Integer> op4 = userList.stream().map(User::getAge).min(Integer::compare);
        System.out.println(op4.get());
    }

归约与收集

 /**
     * 归约
     * reduce(T identity, BinaryOperator) --可以将流中元素反复结合起来,得到一个值。
     */
    @Test
    public void test(){
    
    
        List<User> userList = Arrays.asList(
                new User(18, "张三", "手机", User.Status.BUSY),
                new User(20, "李四", "面包",User.Status.VOCATION),
                new User(20, "赵武", "矿泉水",User.Status.BUSY),
                new User(15, "球球", "鸡腿",User.Status.FREE),
                new User(16, "球球", "鸡腿",User.Status.FREE)
        );

        List<Integer> list = Arrays.asList(1, 2, 3, 4);
        Integer sum = list.stream().reduce(0,(x, y) -> x+y);
        System.out.println(sum);
        System.out.println("-------计算总和-------");
        Optional<Integer> op = userList.stream().map(User::getAge).reduce(Integer::sum);
        System.out.println(op.get());

        /**
         * 收集
         * collect--将流转换为其他形式,接收一个collector接口的实现,用于给Stream中元素做汇总的方法。
         * Collector接口中方法的实现决定了如何对流执行收集(如收集到List、Set、Map)。
         * Collected实用类提供了很多静态方法,可以方便地创建常见收集器实例。
         */
        System.out.println("---------收集到List类型之中-------------");
        List<String> names = userList.stream().map(User::getName).collect(Collectors.toList());
        System.out.println(names);

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

        System.out.println("------------指定容器---------------");
        HashSet<String> hashSet = userList.stream().map(User::getName).
                collect(Collectors.toCollection(HashSet::new));
        System.out.println(hashSet);

        ArrayList<String> arrayList = userList.stream().map(User::getName).
                collect(Collectors.toCollection(ArrayList::new));
        System.out.println(arrayList);

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

        System.out.println("----------平均值--------");
        Double avg = userList.stream().collect(Collectors.averagingDouble(User::getAge));
        System.out.println(avg);

        System.out.println("----------总和--------");
        Double sums = userList.stream().collect(Collectors.summingDouble(User::getAge));
        System.out.println(sums);

        System.out.println("----------最大值--------");
        Optional<User> users = userList.stream().collect(
                Collectors.maxBy((e1, e2) -> Double.compare(e1.getAge(), e2.getAge())));
        System.out.println(users.get());

        System.out.println("----------最小值--------");
        Optional<Integer> min = userList.stream().map(User::getAge).
                collect(Collectors.minBy(Integer::compare));
        System.out.println(min.get());

        System.out.println("----------分组--------");
        Map<User.Status, List<User>> map = userList.stream().collect(
                Collectors.groupingBy(User::getStatus));
        System.out.println(map);

        System.out.println("----------多级分组--------");
        Map<User.Status,Map<String, List<User>>> map2 = userList.stream().
                collect(Collectors.groupingBy(User::getStatus, Collectors.groupingBy((e) -> {
    
    
                    if (((User) e).getAge() <= 18){
    
    
                        return "未成年";
                    }else{
    
    
                        return "成年";
                    }
                })));
        System.out.println(map2);

        System.out.println("----------分区:满足条件地在一个区,不满足在一个区--------");
        Map<Boolean,List<User>> map3 = userList.stream().
                collect(Collectors.partitioningBy((e) -> e.getAge() <= 18));
        System.out.println(map3);

        System.out.println("----------连接字符串--------");
        String str = userList.stream().map(User::getName).
                collect(Collectors.joining(",","这是开头","这是结尾"));
        System.out.println(str);

    }

猜你喜欢

转载自blog.csdn.net/javaasd/article/details/109014248
今日推荐