Java8 新特性之Optional 的使用

/**
 * @author yigen shi
 * @Description <p>不存贮数据</p>
 * <p>不改变数据源</p>
 * <p>延迟执行</p>
 * <p>只能消费一次</p>
 * @date 2019/7/1 19:35
 */
public class StreamTest {

    private String[] arr1 = {"abc", "a", "bc", "abcd"};

    private static class User {

        private Long id;

        private String name;

        private Integer score;

        public User(String name, Integer score) {
            this.name = name;
            this.score = score;
        }

        public User(Long id, String name, Integer score) {
            this.id = id;
            this.name = name;
            this.score = score;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getScore() {
            return score;
        }

        public void setScore(Integer score) {
            this.score = score;
        }

        public void say() {
            System.out.println("hello world");
        }

        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", score=" + score +
                    '}';
        }
    }


    private List<User> userList = new ArrayList<User>() {
        {
            add(new User(1L, "aa", 80));
            add(new User(2L, "bb", 85));
            add(new User(3L, "cc", 90));
            add(new User(4L, "aa", 95));
        }
    };


    /*------------------------流的特性开始----------------------------*/

    /**
     * Stream操作不改变数据源
     */
    @Test
    public void testUnChangeDataSource() {
        List<String> list = Lists.newArrayList("aa", "bb", "cc");
        List<String> filters = list.stream()
                .filter("aa"::equals)
                .collect(Collectors.toList());
        System.out.println(filters); // [aa]
        System.out.println(list); // [aa, bb, cc]
    }

    /**
     * 测试stream的延迟执行 如果stream是立即执行的话,会先打印filter方法里面的begin compare
     */
    @Test
    public void testDelay() {
        Stream<User> stream = userList.stream().filter(student -> {
            student.say();
            return true;
        }).limit(10);
        System.out.println("split-------------------------------------");
        List<User> studentList = stream.collect(Collectors.toList());
        System.out.println(studentList);
    }

    /**
     * 测试stream流的只能一次消费
     */
    @Test(expected = Exception.class)
    public void testConsumeOnlyOnce() {
        Stream<String> stream = Stream.generate(() -> "user").limit(20);
        stream.forEach(System.out::println);
        stream.forEach(System.out::println);
    }
    /*------------------------流的特性结束----------------------------*/


    /*------------------------流的创建开始----------------------------*/

    /**
     * 通过数组创建流
     */
    @Test
    public void testArrayStream() {
        //1.通过Arrays.stream
        //1.1基本类型
        int[] arr = new int[]{1, 2, 34, 5};
        IntStream intStream = Arrays.stream(arr);
        long[] lrr = new long[]{1, 2, 3, 4};
        LongStream longStream = Arrays.stream(lrr);
        //1.2引用类型
        User[] studentArr = new User[]{new User("s1", 29), new User("s2", 27)};
        Stream<User> studentStream = Arrays.stream(studentArr);
        //2.通过Stream.of
        Stream<Integer> stream1 = Stream.of(1, 2, 34, 5, 65);
        //注意生成的是int[]的流
        Stream<int[]> stream2 = Stream.of(arr, arr);
        stream2.forEach(System.out::println);
    }

    /**
     * 通过集合创建流
     */
    @Test
    public void testCollectionStream() {
        // 通过List创建流
        List<String> list = Arrays.asList("11212", "dfd", "2323", "dfhgf");
        Stream<String> listStream = list.stream();
        // 通过Set创建流
        HashSet<String> set = new HashSet<>(list);
        Stream<String> setStream = set.parallelStream();
        // 通过队列创建流
        Queue<String> queue = new ArrayDeque<>();
        Stream<String> queueStream = queue.stream();
        // 通过栈创建流
        Stack<String> stack = new Stack<>();
        Stream<String> stackStream = stack.stream();
        // 通过Vector创建流
        Vector<String> vector = new Vector<>();
        Stream<String> vectorStream = vector.stream();
    }

    @Test
    public void testParallelStream() {
        List<String> strs = Arrays.asList("11212", "dfd", "2323", "dfhgf");
        // 创建串行流(普通流)
        Stream<String> stream = strs.stream();
        // 创建并行流
        Stream<String> stringStream = strs.parallelStream();
    }

    /**
     * 创建空的流
     */
    @Test
    public void testEmptyStream() {
        //创建一个空的stream
        Stream<Integer> stream = Stream.empty();
    }

    /**
     * 创建无限流
     */
    @Test
    public void testUnlimitStream() {
        //创建无限流,通过limit提取指定大小
        Stream.generate(() -> "number" + new Random().nextInt()).limit(100)
                .forEach(System.out::println);
        Stream.generate(() -> new User("name", 10)).limit(20).forEach(System.out::println);
    }


    /**
     * 产生规律的数据
     */
    @Test
    public void testUnLimitStream1() {
        Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::println);
        Stream.iterate(0, x -> x).limit(10).forEach(System.out::println);
        //Stream.iterate(0,x->x).limit(10).forEach(System.out::println);与如下代码意思是一样的
        Stream.iterate(0, UnaryOperator.identity()).limit(10).forEach(System.out::println);
    }

    /*------------------------流的创建结束----------------------------*/


    /*------------------------流的操作开始----------------------------*/

    /**
     * 过滤 列出班上超过85分的学生姓名,并按照分数降序输出用户名字
     */
    @Test
    public void testFilter() {
        List<String> studentList = userList.stream()
                .filter(x -> x.getScore() > 85)
                .sorted(Comparator.comparing(User::getScore).reversed())
                .map(User::getName)
                .collect(Collectors.toList());
        System.out.println(studentList);
    }


    /**
     * 分组
     */
    @Test
    public void testGroupBy() {
        // 根据分数分组
        Map<Integer, List<User>> map = userList.stream()
                .filter(x -> x.getScore() > 85)
                .collect(Collectors.groupingBy(User::getScore));
        System.out.println(map);
        // 根据名字分组
        Map<String, List<User>> nameMap = userList.stream()
                .collect(Collectors.groupingBy(User::getName));
        System.out.println(nameMap);
    }

    /**
     * 去重操作
     */
    @Test
    public void testDistinct() {
        List<Integer> list = Lists.newArrayList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6);
        List<Integer> result = list.stream().distinct().collect(Collectors.toList());
        System.out.println(result);
    }





    /*--------------------stream的操作 ----------------------*/

    /**
     * map:转换流,将一种类型的流转换为另外一种流 map把一种类型的流转换为另外一种类型的流 将String数组中字母转换为小写
     */
    @Test
    public void testMap() {
        String[] arr = new String[]{"yes", "YES", "no", "NO"};
        Arrays.stream(arr).map(String::toLowerCase).forEach(System.out::println);
    }

    /**
     * filter:过滤流,过滤流中的元素
     */
    @Test
    public void testFilter01() {
        Integer[] arr = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        Arrays.stream(arr).filter(x -> x > 3 && x < 8).forEach(System.out::println);
        Arrays.stream(arr).filter(x -> x > 3)
                .filter(x -> x < 8).forEach(System.out::println);
    }

    private static class SysUser {

        private Long id;

        private String name;

        private String description;

        private List<SysRole> roles;

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public List<SysRole> getRoles() {
            return roles;
        }

        public void setRoles(List<SysRole> roles) {
            this.roles = roles;
        }

    }

    private static class SysRole {

        private Long id;

        private String name;

        private String description;

        private List<SysPermission> permissions;

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public List<SysPermission> getPermissions() {
            return permissions;
        }

        public void setPermissions(List<SysPermission> permissions) {
            this.permissions = permissions;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    private static class SysPermission {

        private Long id;

        private String name;

        private String description;

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }


        @Override
        public String toString() {
            return "SysPermission{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", description='" + description + '\'' +
                    '}';
        }
    }


    /**
     * flapMap:拆解流
     */
    @Test
    public void testFlapMap1() {
        String[] arr1 = {"a", "b", "c", "d"};
        String[] arr2 = {"e", "f", "c", "d"};
        String[] arr3 = {"h", "j", "c", "d"};
        // Stream.of(arr1, arr2, arr3).flatMap(x -> Arrays.stream(x)).forEach(System.out::println);
        Stream.of(arr1, arr2, arr3).flatMap(Arrays::stream).forEach(System.out::println);
    }

    /**
     * flapMap:拆解流,将流中每一个元素拆解成一个流
     */
    @Test
    public void testFlatMap() {
        List<SysPermission> permissions = new ArrayList<>();
        SysPermission permission = new SysPermission();
        permission.setId(1L);
        permission.setName("管理员权限");
        permission.setDescription("超级管理员权限");
        permissions.add(permission);

        List<SysRole> roles = new ArrayList<>();
        SysRole sysRole = new SysRole();
        sysRole.setId(1L);
        sysRole.setName("ADMIN");
        sysRole.setDescription("管理员角色");
        sysRole.setPermissions(permissions);
        roles.add(sysRole);

        SysUser user = new SysUser();
        user.setId(1L);
        user.setName("stream");
        user.setDescription("stream flatMap 拆解流");
        user.setRoles(roles);
        // 未判空处理
        List<String> permission1 = roles.stream()
                .flatMap(sysRole1 -> sysRole1.getPermissions().stream())
                .map(SysPermission::getName)
                .collect(Collectors.toList());
        System.out.println(permission1);

        user.setRoles(null);

        // 空指针异常
    /*List<String> permission2 = roles.stream()
        .flatMap(sysRole1 -> sysRole1.getPermissions().stream())
        .map(SysPermission::getName)
        .collect(Collectors.toList());
    System.out.println(permission2);*/
        List<String> permission3 = (CollectionUtils.isEmpty(user.getRoles())
                ? new ArrayList<SysRole>() : user.getRoles()).stream()
                .flatMap(role -> (CollectionUtils.isEmpty(role.getPermissions())
                        ? new ArrayList<SysPermission>() : role.getPermissions()).stream())
                .map(SysPermission::getName)
                .collect(Collectors.toList());
        System.out.println(permission3);

        List<String> permission4 = Optional.ofNullable(user.getRoles())
                .orElse(new ArrayList<>()).stream()
                .flatMap(role -> Optional.ofNullable(role.getPermissions())
                        .orElse(new ArrayList<>()).stream())
                .map(SysPermission::getName)
                .collect(Collectors.toList());
        System.out.println(permission4);

    }


    /**
     * Comparator.comparing是一个键提取的功能 以下两个语句表示相同意义
     */
    @Test
    public void testSorted1_() {
        // 按照字符长度排序
        Arrays.stream(arr1).sorted((x, y) -> {
            if (x.length() > y.length()) {
                return 1;
            } else if (x.length() < y.length()) {
                return -1;
            } else {
                return 0;
            }
        }).forEach(System.out::println);
        Arrays.stream(arr1).sorted(Comparator.comparing(String::length)).forEach(System.out::println);
    }

    /**
     * 倒序 reversed(),java8泛型推导的问题,所以如果comparing里面是非方法引用的lambda表达式就没办法直接使用reversed()
     * Comparator.reverseOrder():也是用于翻转顺序,用于比较对象(Stream里面的类型必须是可比较的) Comparator.
     * naturalOrder():返回一个自然排序比较器,用于比较对象(Stream里面的类型必须是可比较的)
     */
    @Test
    public void testSorted2_() {
        Arrays.stream(arr1).sorted(Comparator.comparing(String::length).reversed())
                .forEach(System.out::println);
        Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println);
        Arrays.stream(arr1).sorted(Comparator.naturalOrder()).forEach(System.out::println);
    }

    /**
     * thenComparing 先按照首字母排序 之后按照String的长度排序
     */
    @Test
    public void testSorted3_() {
        Arrays.stream(arr1).sorted(Comparator.comparing(this::com1).
                thenComparing(String::length)).forEach(System.out::println);
    }

    private char com1(String x) {
        return x.charAt(0);
    }

    /*--------------提取流和合并流---------------------*/
    String[] arr01 = new String[]{"a", "b", "c", "d"};
    String[] arr02 = new String[]{"d", "e", "f", "g"};
    String[] arr03 = new String[]{"i", "j", "k", "l"};

    /**
     * limit,限制从流中获得前n个数据
     */
    @Test
    public void testLimit() {
        Stream.iterate(1, x -> x + 2).limit(10).forEach(System.out::println);
    }

    /**
     * skip,跳过前n个数据
     */
    @Test
    public void testSkip() {
        //Stream.of(arr1).skip(2).limit(2).forEach(System.out::println);
        Stream.iterate(1, x -> x + 2).skip(1).limit(5).forEach(System.out::println);
    }


    /**
     * 可以把两个stream合并成一个stream(合并的stream类型必须相同) 只能两两合并
     */
    @Test
    public void testConcat() {
        Stream<String> stream1 = Stream.of(arr01);
        Stream<String> stream2 = Stream.of(arr02);
        Stream.concat(stream1, stream2).distinct().forEach(System.out::println);
    }


    private String[] arr05 = new String[]{"b", "ab", "abc", "abcd", "abcde"};

    /**
     * max、min 最大最小值
     */
    @Test
    public void testMaxAndMin() {
        Stream.of(arr05).max(Comparator.comparing(String::length)).ifPresent(System.out::println);
        Stream.of(arr05).min(Comparator.comparing(String::length)).ifPresent(System.out::println);
    }

    /**
     * count 计算数量
     */
    @Test
    public void testCount() {
        long count = Stream.of(arr05).count();
        System.out.println(count);
    }

    /**
     * findFirst 查找第一个
     */
    @Test
    public void testFindFirst() {
        String str = Stream.of(arr05).parallel().filter(x -> x.length() > 3).findFirst()
                .orElse("nothing");
        System.out.println(str);
    }

    /**
     * findAny 找到所有匹配的元素 对并行流十分有效 只要在任何片段发现了第一个匹配元素就会结束整个运算
     */
    @Test
    public void testFindAny() {
        Optional<String> optional = Stream.of(arr05).parallel().filter(x -> x.length() > 3).findAny();
        optional.ifPresent(System.out::println);
    }

    /**
     * anyMatch 是否含有匹配元素
     */
    @Test
    public void testAnyMatch() {
        Boolean aBoolean = Stream.of(arr05).anyMatch(x -> x.startsWith("a"));
        System.out.println(aBoolean);
        boolean a = Stream.of(arr05).allMatch(s -> s.startsWith("a"));
        System.out.println(a);
    }

    /*--------- Optional类型通常聚合操作会返回一个Optional类型,Optional表示一个安全的指定结果类型,
    所谓的安全指的是避免直接调用返回类型的null值而造成空指针异常,调用optional.ifPresent()可以判断返回值是否为空,
    或者直接调用ifPresent(Consumer consumer)在结果部位空时进行消费操作;调用optional.get()获取返回值。
    通常的使用方式如下:----*/
    @Test
    public void testStream1() {
        Optional<Integer> optional = Stream.of(1, 2, 3)
                .filter(x -> x > 1)
                .reduce((x, y) -> x + y);
        optional.ifPresent(System.out::println);
    }

    @Test
    public void testOptional() {
        List<String> list = new ArrayList<String>() {
            {
                add("user1");
                add("user2");
            }
        };
        Optional<String> opt = Optional.of("andy with u");
        opt.ifPresent(list::add);
        list.forEach(System.out::println);
    }

    /**
     * 使用Optional可以在没有值时指定一个返回值,例如
     */
    @Test(expected = RuntimeException.class)
    public void testOptional2() {
        Integer[] arr = new Integer[]{4, 5, 6, 7, 8, 9};
        Integer result = Stream.of(arr).filter(x -> x > 9)
                .max(Comparator.naturalOrder())
                .orElse(-1);
        System.out.println(result);
        Integer result1 = Stream.of(arr).filter(x -> x > 9)
                .max(Comparator.naturalOrder())
                .orElse(-1);
        System.out.println(result1);
        Integer result2 = Stream.of(arr).filter(x -> x > 9)
                .max(Comparator.naturalOrder())
                .orElseThrow(RuntimeException::new);
        System.out.println(result2);
    }


    /**
     * Optional的创建 采用Optional.empty()创建一个空的Optional,使用Optional.of()创建指定值的Optional。
     * 同样也可以调用Optional对象的map方法进行Optional的转换,调用flatMap方法进行Optional的迭代
     */
    @Test
    public void testStream02() {
        Optional<User> studentOptional = Optional.of(new User("user1", 21));
        Optional<String> optionalStr = studentOptional.map(User::getName);
        System.out.println(optionalStr.get());
    }


    public static Optional<Double> inverse(Double x) {
        return x == 0 ? Optional.empty() : Optional.of(1 / x);
    }

    @Test
    public void testInverse() {
        Optional<Double> inverse = StreamTest.inverse(100.00);
        System.out.println(inverse.get());
    }

    public static Optional<Double> squareRoot(Double x) {
        return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
    }

    @Test
    public void testSquareRoot() {
        Optional<Double> aDouble = StreamTest.squareRoot(100.00);
        System.out.println(aDouble.get());
    }

    /**
     * Optional的迭代
     */
    @Test
    public void testStream2() {
        double x = 4d;
        Optional<Double> result1 = inverse(x).flatMap(StreamTest::squareRoot);
        result1.ifPresent(System.out::println);
        Optional<Double> result2 = Optional.of(4.0).flatMap(StreamTest::inverse)
                .flatMap(StreamTest::squareRoot);
        result2.ifPresent(System.out::println);
    }

    /* ----------------收集结果 ------------------------*/
    User[] users;

    @Before
    public void init01() {
        users = new User[20];
        for (int i = 0; i < 10; i++) {
            User user = new User((long) i, "user", 60 - i);
            users[i] = user;
        }
        for (int i = 10; i < 20; i++) {
            User user = new User((long) i, "user" + i, 100 - i);
            users[i] = user;
        }
    }


    @Test
    public void testCollect1() {
        // 生成List
        List<User> list = Arrays.stream(users).collect(Collectors.toList());
        list.forEach(System.out::println);
        // 生成Set
        Set<User> set = Arrays.stream(users).collect(Collectors.toSet());
        set.forEach(System.out::println);
        // 如果包含相同的key,则需要提供第三个参数,否则报错
        Map<String, Integer> map = Arrays.stream(users)
                .collect(Collectors.toMap(User::getName, User::getScore, (s, a) -> s + a));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }


    /**
     * 生成数组
     */
    @Test
    public void testCollect2() {
        User[] s = Arrays.stream(users).toArray(User[]::new);
        for (User value : s) {
            System.out.println(value);
        }
    }

    /**
     * 指定生成的类型
     */
    @Test
    public void testCollect3() {
        HashSet<User> s = Arrays.stream(users).collect(Collectors.toCollection(HashSet::new));
        s.forEach(System.out::println);
    }


    /**
     * 统计
     */
    @Test
    public void testCollect4() {
        IntSummaryStatistics summaryStatistics = Arrays.stream(users)
                .collect(Collectors.summarizingInt(User::getScore));
        System.out.println("getAverage->" + summaryStatistics.getAverage());
        System.out.println("getMax->" + summaryStatistics.getMax());
        System.out.println("getMin->" + summaryStatistics.getMin());
        System.out.println("getCount->" + summaryStatistics.getCount());
        System.out.println("getSum->" + summaryStatistics.getSum());
    }

    /* -----------------分组和分片 ---------------*/

    /**
     * 分组和分片的意义是,将collect的结果集展示位Map的形式,通常的用法如下:
     */
    @Test
    public void testGroupByName1() {
        Map<String, List<User>> map = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    /**
     * downstream指定类型
     */
    @Test
    public void testGroupByName2() {
        Map<String, Set<User>> map = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName, Collectors.toSet()));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    /**
     * 根据名字分组并映射value值
     */
    @Test
    public void testGroupByNameAndMapping() {
        Map<String, List<Integer>> map = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName,
                        Collectors.mapping(User::getScore, Collectors.toList())));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    /**
     * 根据多个字段分组
     */
    @Test
    public void groupByMultipleFields() {
        Map<String, Map<Integer, User>> map = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName,
                        Collectors.toMap(User::getScore, Function.identity(), (old, replace) -> replace)));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    /**
     * 如果只有两类,使用partitioningBy会比groupingBy更有效率
     */
    @Test
    public void testPartitioningBy() {
        Map<Boolean, List<User>> map = Arrays.stream(users)
                .collect(Collectors.partitioningBy(x -> x.getScore() > 50));
        map.forEach((x, y) -> System.out.println(x + "->" + y));
    }


    /**
     * downstream 聚合操作
     */
    @Test
    public void testGroupBy3() {
        // counting
        Map<String, Long> map1 = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName, Collectors.counting()));
        map1.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    @Test
    public void testSummingInt() {
        // summingInt
        Map<String, Integer> map2 = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName, Collectors.summingInt(User::getScore)));
        map2.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    @Test
    public void testMaxBy() {
        // maxBy
        Map<String, Optional<User>> map3 = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName,
                        Collectors.maxBy(Comparator.comparing(User::getScore))));
        map3.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    @Test
    public void testMapping() {
        // mapping
        Map<String, Set<Integer>> map4 = Arrays.stream(users)
                .collect(Collectors.groupingBy(User::getName,
                        Collectors.mapping(User::getScore, Collectors.toSet())));
        map4.forEach((x, y) -> System.out.println(x + "->" + y));
    }

    /*-----------------------------原始类型流--------------------------------*/
    /**
     * 在数据量比较大的情况下,将基本数据类型(int,double…)包装成相应对象流的做法是低效的,
     * 因此,我们也可以直接将数据初始化为原始类型流,在原始类型流上的操作与对象流类似,我们只需要记住两点:
     * 1、原始类型流的初始化
     * 2、原始类型流与流对象的转换
     * DoubleStream doubleStream;
     * IntStream intStream;
     */
    /**
     * 原始类型流的初始化
     */
    DoubleStream doubleStream;
    IntStream intStream;

    @Before
    public void testStream002() {
        doubleStream = DoubleStream.of(0.1, 0.2, 0.3, 0.8);
        intStream = IntStream.of(1, 3, 5, 7, 9);
        IntStream stream1 = IntStream.rangeClosed(0, 100);
        IntStream stream2 = IntStream.range(0, 100);
    }

    /**
     * 流与原始类型流的转换
     */
    @Test
    public void testStream03() {
        Stream<Double> stream = doubleStream.boxed();
        doubleStream = stream.mapToDouble(Double::new);
    }

    /*--------------- 并行流 --------------------------*/

    /**
     * 我们调用peek方法来瞧瞧并行流和串行流的执行顺序,peek方法顾名思义,就是偷窥流内的数据, peek方法声明为Streampeek(Consumer
     * action);加入打印程序可以观察到通过流内数据,见如下代码:
     */
    public void peek1(int x) {
        System.out.println(Thread.currentThread().getName() + ":->peek1->" + x);
    }

    public void peek2(int x) {
        System.out.println(Thread.currentThread().getName() + ":->peek2->" + x);
    }

    public void peek3(int x) {
        System.out.println(Thread.currentThread().getName() + ":->final result->" + x);
    }

    /**
     * peek,监控方法 串行流和并行流的执行顺序
     */
    @Test
    public void testPeek() {
        Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10);
        stream.peek(this::peek1).filter(x -> x > 5)
                .peek(this::peek2).filter(x -> x < 8)
                .peek(this::peek3)
                .forEach(System.out::println);
    }

    @Test
    public void testPeekPal() {
        Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(10).parallel();
        stream.peek(this::peek1).filter(x -> x > 5)
                .peek(this::peek2).filter(x -> x < 8)
                .peek(this::peek3)
                .forEach(System.out::println);
    }

    @Test
    public void testToMap() {
        List<User> list = new ArrayList<>();
        list.add(new User(1L, "haha", 60));
        list.add(new User(2L, "rere", 70));
        list.add(new User(3L, "fefe", 80));

        Map<Long, User> map = list.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        System.out.println(map);
        System.out.println(map.get(1L).getName());

        Map<Long, String> collect = list.stream().collect(Collectors.toMap(User::getId, User::getName));
        System.out.println(collect);

        // 解决key冲突
        list.add(new User(1L, "feifei", 90));
        Map<Long, User> collect1 = list.stream()
                .collect(Collectors.toMap(User::getId, Function.identity(), (old, replace) -> replace));
        System.out.println(collect1);
    }

    @Test
    public void testDistinct01() {
        List<String> list = Lists.newArrayList("aa", "bb", "cc", "aa");
        list.stream().distinct().forEach(System.out::println);
    }


    /**
     * 根据名字和分数分组
     */
    @Test
    public void testUserGroupBy() {
        List<User> list = new ArrayList<>();
        User user1 = new User(1L, "aa", 86);
        list.add(user1);
        User user2 = new User(2L, "bb", 90);
        list.add(user2);
        User user3 = new User(3L, "cc", 95);
        list.add(user3);
        Map<User, List<User>> collect = list.stream().collect(Collectors.groupingBy(
                record -> new User(record.getName(), record.getScore())));
        System.out.println(collect);
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值