Stream API示例

import lombok.Data;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

public class StreamAPI {

    /**
     *
     * Comparator.reverseOrder()是让某个条件进行倒序排序.
     * reversed()是让他前面的字段进行倒序。
     *
     * 例如:Comparator.comparing(名称).reversed(),此时名称倒序;
     * Comparator.comparing(名称).thenComparing(状态).reversed(),此时名称和状态进行倒序。
     *
     * Comparator.comparing(名称).thenComparing(状态).reversed().thenComparing(年龄),此时名称和状态会倒序,年龄会升序。
     *
     * 加多个.reversed()
     * Comparator.comparing(状态).reversed().thenComparing(年龄).reversed(),最终结果是只有年龄倒排,状态未排序

     */

    /**
     * 练习1:让年龄进行倒序排序。
     */
    @Test
    public void test1() {
        /*
         * Comparator.comparing(放实体类名称::放列名):添加排序字段;
         * reversed():倒序。
         * collect(Collectors.toList()):转成集合。
         * forEach(System.out::println):打印循环。
         */
        List<User> userList = generatorUserList();
//        userList.stream()
//                .sorted(Comparator.comparing(User::getAge).reversed())//reversed()是让其前面得所有字段都倒排
//                .collect(Collectors.toList())
//                .forEach(System.out::println);


//        List<User> userList2 = generatorUserList();
//        userList2.stream()
//                .sorted(Comparator.comparing(User::getAge, Comparator.reverseOrder()))//Comparator.reverseOrder()是让某个条件进行倒序排序
//                .collect(Collectors.toList()).forEach(System.out::println);

        userList.stream().sorted(Comparator.comparing(User::getAge).reversed())
                .collect(Collectors.toList()).forEach(System.out::println);
    }

    /**
     * 练习2:让使用状态进行升序排序。
     */
    @Test
    public void test2() {
        List<User> userList = generatorUserList();
        //默认是升序,所以只需要把排序字段放进去就行了。
        userList.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList()).forEach(System.out::println);
    }

    /**
     * 练习3:让使用先状态和后年龄都进行倒序排序。
     */
    @Test
    public void test3() {
        List<User> userList = generatorUserList();
        userList.stream()
                //先根据使用状态倒序,而王五使用状态为2,所以王五排在第一。
                //而李四和张三使用状态都是1,就会触发另一个排序条件根据年龄排序
                .sorted(Comparator.comparing(User::getState).thenComparing(User::getAge).reversed())
                .collect(Collectors.toList())
                .forEach(System.out::println);

        //写法2
        List<User> userList2 = generatorUserList();
        userList2.stream()
                .sorted(
                        Comparator.comparing(User::getState, Comparator.reverseOrder())//根据state倒排
                        .thenComparing(User::getAge, Comparator.reverseOrder())//根据age倒排
                )
                .forEach(System.out::println);
    }

    /**
     * 练习4:让使用状态和年龄都进行升序排序。
     */
    @Test
    public void test4() {
        List<User> userList = generatorUserList();
        //默认就是升序
        userList.stream().sorted(Comparator.comparing(User::getState).thenComparing(User::getAge)).forEach(System.out::println);
    }

    /**
     * 练习5:让使用状态进行升序排序,年龄进行倒序排序,创建时间进行倒序排序。名字正排序
     * 注意:假如多个排序条件的排序方向不一致,需要倒序的字段应该用Comparator.reverseOrder(),每个倒排得字段单独写。
     */
    @Test
    public void test5() {
        List<User> userList = generatorUserList();
        userList.stream()
                .sorted(
                        Comparator.comparing(User::getState)
                                .thenComparing(User::getAge, Comparator.reverseOrder())
                                .thenComparing(User::getCreateTime,Comparator.reverseOrder())
                                .thenComparing(User::getName)
                )
                .forEach(System.out::println);
    }

    /**
     * 练习6,按 State 分组 组成 Map<Ingeter, List<User>>的结构
     */
    @Test
    public void test6() {
        List<User> userList = generatorUserList();
        Map<Integer, List<User>> stateToUserList = userList.stream().collect(Collectors.groupingBy(User::getState));
        System.out.println(stateToUserList);
    }

    /**
     * 联系7 根据姓名作为key, User对象为val,组成map<String, User>
     *     如果是根据state, 因为元素不唯一, 所以会抛出异常
     *     根据姓名为key, age为val组成 map<String, Ingeter>
     */
    @Test
    public void test7() {
        List<User> userList = generatorUserList();
        Map<String, User> nameToUser = userList.stream().collect(Collectors.toMap(User::getName, user -> user));
        //下面这样也行
//        Map<String, User> nameToUser = userList.stream().collect(Collectors.toMap(User::getName, user -> {return user;}));
        System.out.println(nameToUser);

        //在映射时, 把年龄加1再返回
        Map<String, User> nameToAge0 = userList.stream().collect(Collectors.toMap(User::getName, user -> { user.setAge(user.age+1); return user;}));
        System.out.println(nameToAge0);

        //那么如果分组的字段是一个非唯一的,比如state, 会报错
//        Map<Integer, User> stateToUser = userList.stream().collect(Collectors.toMap(User::getState, user -> user));
//        System.out.println(stateToUser);

        //根据姓名为key, age为val组成 map<String, Ingeter>
        //写法1
        Map<String, Integer> nameToAge = userList.stream().collect(Collectors.toMap(User::getName, User::getAge));
        System.out.println(nameToAge);
        //写法2
        Map<String, Integer> nameToAge2 = userList.stream().collect(Collectors.toMap(User::getName, user -> {return user.age;}));
        System.out.println(nameToAge2);

        Map<String, Integer> nameToAge3 = userList.stream().collect(Collectors.toMap(User::getName, user -> { user.setAge(user.age+1); return user.age;}));
        System.out.println(nameToAge3);

    }

    /**
     * 练习8 按名字去重
     */
    @Test
    public void test8() {
        List<User> userList = generatorUserList();
        Set<String> collect1 = userList.stream().distinct().map(User::getName).collect(Collectors.toSet());
        System.out.println(collect1);
        return;
    }

    /**
     * 按名字统计数量
     */
    @Test
    public void test9() {
        List<User> userList = generatorUserList();
        Map<String, Long> collect = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting()));
        System.out.println(collect);
        return;
    }

    /**
     * 求年龄最大值、最小值
     */
    @Test
    public void test10() {
        List<User> userList = generatorUserList();
        //如果有年龄一样的,会按list顺序取第一条, 所以除非能唯一, 否则多维度需要使用排序来获取值
        Optional<User> min = userList.stream().min(Comparator.comparing(User::getAge));
        System.out.println("min = " + min);
    }

    /**
     * 获取某个字段的 最大值、最小值、求和、统计、计数
     */
    @Test
    public void test11() {
        List<User> userList = generatorUserList();
        IntSummaryStatistics collect = userList.stream().collect(Collectors.summarizingInt(User::getAge));
        double average = collect.getAverage();
        int max = collect.getMax();
        int min = collect.getMin();
        long sum = collect.getSum();
        long count = collect.getCount();
        System.out.println("collect = " + collect);

        //单独对某个字段汇总
        int sum1 = userList.stream().mapToInt(User::getAge).sum();
        System.out.println("sum = " + sum1);

        double avg1 = userList.stream().collect(Collectors.averagingDouble(User::getAge));
        System.out.println("avg1 = " + avg1);

        OptionalDouble avg2 = userList.stream().mapToDouble(User::getAge).average();
        if (avg2.isPresent()) {
            System.out.println("avg2 = " + avg2);
        }
    }

    /**
     * 按名字分组, 统计年龄相关的 计数, 总数,最大,最小,平均
     */
    @Test
    public void test12() {
        List<User> userList = generatorUserList();
        Map<String, IntSummaryStatistics> collect = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.summarizingInt(User::getAge)));
        for(Map.Entry<String, IntSummaryStatistics> entry : collect.entrySet()) {
            System.out.println(entry.getKey()+"-----"+entry.getValue());
        }
    }

    /**
     * 生成用户示例用户列表
     * @return
     */
    private List<User> generatorUserList() {
        List<User> list = new ArrayList<>();

        User user1 = new User();
        user1.setName("19");
        user1.setAge(18);
        user1.setState(1);
        user1.setCreateTime(new Date());
        list.add(user1);

        User user2 = new User();
        user2.setName("1");
        user2.setAge(22);
        user2.setState(1);
        user2.setCreateTime(new Date());
        list.add(user2);

        User user3 = new User();
        user3.setName("2");
        user3.setAge(15);
        user3.setState(2);
        user3.setCreateTime(new Date());
        list.add(user3);

        User user4 = new User();
        user4.setName("23");
        user4.setAge(15);
        user4.setState(2);
        user4.setCreateTime(new Date());
        list.add(user4);

        User user5 = new User();
        user5.setName("23");
        user5.setAge(18);
        user5.setState(2);
        user5.setCreateTime(new Date());
        list.add(user5);
        return list;
    }







    @Data
    class User{
        private String name;

        private Integer age;

        private Integer state;

        private Date createTime;

    }
}