Java语法新特性-函数接口、Stream、Optional

Java语法新特性-函数接口、Stream、Option

1.四大函数接口

public class FunctionInterfaceDemo {

    public static void main(String[] args) {
        test04();
    }

    /**
     * Supplier 没有入参,有出参
     */
    public static void test04() {
        Supplier<Integer> supplier1 = new Supplier<Integer>() {
            @Override
            public Integer get() {
                System.out.println(10);
                return 10;
            }
        };

        System.out.println(supplier1.get());

        Supplier<Integer> supplier2 = () -> {
            System.out.println(11);
            return 11;
        };
        System.out.println(supplier2.get());
    }

    /**
     * Consumer 有入参,没有返回值
     */
    public static void test03() {
        // Consumer<Integer>,消费型接口,只有输入,没有返回值。
        Consumer<Integer> consumer1 = new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        };

        consumer1.accept(10);

        Consumer<Integer> consumer2 = v -> System.out.print(v + 1);
        Consumer<Integer> consumer3 = System.out::println;
        consumer2.accept(11);
    }

    /**
     * Predicate 预言
     */
    public static void test02() {
        // Predicate<Integer>,泛型Integer为输入类型,Predicate为对输入值操作后的布尔值。
        Predicate<Integer> predicate1 = new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer > 0;
            }
        };

        System.out.println(predicate1.test(10));

        Predicate<Integer> predicate2 = v -> v > 0;
        System.out.println(predicate2.test(10));
    }

    /**
     * Function 有入参,有出参
     */
    public static void test01() {
        // Function<String, String>,第一个泛型是输入值,第二个泛型是输出值
        Function<String, String> function1 = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s + s;
            }
        };

        System.out.println(function1.apply("tom")); // tomtom

        // lambda
        Function<String, String> function2 = s -> s + s + s;

        System.out.println(function2.apply("bob")); // bobbobbob
    }
}

2.Stream

public class StreamDemo {

    public static void main(String[] args) {
        User user1 = new User(1, "tom1", 11, "t1");
        User user2 = new User(2, "tom2", 12, "t2");
        User user3 = new User(3, "tom3", 13, "t3");
        User user4 = new User(4, "tom4", 14, "t4");
        User user5 = new User(5, "tom4", 15, "t4");

        // List用于数据存储
        List<User> users = new ArrayList<>();
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);

        test06(users);
    }
    
    /**
     * flatMap
     */
    public static void test12() {
        List<List<Integer>> list = new ArrayList<>();

        List<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);

        List<Integer> list2 = new ArrayList<>();
        list2.add(10);
        list2.add(20);
        list2.add(30);

        List<Integer> list3 = new ArrayList<>();
        list3.add(100);
        list3.add(200);
        list3.add(300);

        list.add(list1);
        list.add(list2);
        list.add(list3);

        // flatMap用于将数据扁平化,用来处理有嵌套关系的数据。
        // 如User{ List<Book> books>},用户数据中包含了图书信息,
        // 想获取所有用户的图像信息(即获取到List<Book>),就可以使用flatMap。
        // users.stream().flatMap(v -> v.getBooks().stream()).collect(Collectors.toList()));
        // [1, 2, 3, 10, 20, 30, 100, 200, 300]
        System.out.println(list.stream().flatMap(v -> v.stream()).collect(Collectors.toList()));
        System.out.println(list.stream().flatMap(Collection::stream).collect(Collectors.toList()));
    }
    
    /**
     * dropWhile takeWhile
     */
    public static void test11() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);

        // 删除第一个不满足条件的元素之前的所有元素,只要后面的其他元素。
        // [2, 3, 4, 5]
        System.out.println(list.stream().dropWhile(v -> v == 1).toList());

        // 只保留流中第一个不满足条件的元素之前的所有元素。
        // [1]
        System.out.println(list.stream().takeWhile(v -> v == 1).toList());
    }
    
    /**
	 * allMatch、anyMatch、noneMatch、reduce。
     */
    public static void test09() {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);

        // 都匹配
        System.out.println(list.stream().allMatch(v -> v == 4)); // false
        // 任何一个匹配
        System.out.println(list.stream().anyMatch(v -> v == 4)); // true
        // 所有的都没有匹配上。
        System.out.println(list.stream().noneMatch(v -> v > 10)); // true

        // 将流中元素相加
        System.out.println(list.stream().reduce(Integer::sum).get()); // 10
        // 获取元素第一个值
        System.out.println(list.stream().reduce((first, second) -> first).get()); // 1
        // 获取元素第二个值
        System.out.println(list.stream().reduce((first, second) -> second).get()); // 4
    }
    
    /**
	 * map、peek。
     */
    public static void test08() {
        List<User> list = new ArrayList<>();
        list.add(new User(1, "1"));
        list.add(new User(2, "2"));
        list.add(new User(3, "3"));
        list.add(new User(4, "4"));
        // 从小到大排序
        list.stream().sorted().forEach(System.out::println);

        // 从大到小排序,倒序。
        list.stream().sorted((o1, o2) -> -o1.id - o2.id).forEach(System.out::println);

        // map和peek的区别,map操作后可以改变流的返回值值;
        // peek不能改变返回值,只是对流中元素进行操作。
        list.stream().map(User::getId).forEach(System.out::println);
        list.stream().peek(v -> v.setId(v.getId() - 1)).forEach(System.out::println);
        
        String names02 = list.stream().map(User::getName)
                .collect(Collectors.joining(",", "[", "]"));
        // [tom1,tom2,tom3,tom4,tom4]
        System.out.println(names02);
    }
    
    public static void test07() {
        // 通过数组创建流。
        int[] a = {1, 2, 3, 4, 5};
        Arrays.stream(a).forEach(System.out::println);

        // Stream创建流
        Stream.of(1, 2, 3).forEach(System.out::println);

        // 创建一个无限循环流。第二个参数是函数接口,函数的入参是第一个参数,
        // 函数的返回值是对第一个参数的操作结果。
        Stream.iterate(1, v -> v).forEach(System.out::println);

        // 创建一个无限循环的流。
        Stream.generate(Math::random).forEach(System.out::println);
    }

    /**
     * List中对象id值加10
     * @param list
     */
    public static void test06(List<User> list) {
        List<User> collect = list.stream().peek((v1) -> v1.setId(v1.getId() + 10))
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    /**
     * 分组。collect 收集器
     * @param list
     */
    public static void test05(List<User> list) {
        // 通过List中对象的某一个属性进行分组
        Map<String, List<User>> map = list.stream().collect(Collectors.groupingBy(User::getAddr));
        System.out.println(map);
    }

    public static void test04(List<User> list) {
        // 对Id列进行求和
        Integer integer = list.stream().mapToInt(User::getId).sum();
        System.out.println(integer);
    }

    public static void test03(List<User> list) {
        // List转Map,将List中对象的某一个属性作为Map的key,这个属性对应的对象作为Map的value。
        // v -> v,每次处理的值,这里可以对值进行操作,或者返回转换为其他对象。
        // 当key重复了就会走到(v1, v2) -> v2中,由这个函数确定重复时需要保存哪个值。
        // (v1, v2) -> v1,当出现多个key时,保留之前的值。
        // (v1, v2) -> v2,当出现多个key时,进行覆盖,保存之后的值。
        Map<String, User> stringUserMap01 = list.stream()
                .collect(Collectors.toMap(User::getName, v -> v, (v1, v2) -> v2));
        System.out.println(stringUserMap01);

        // List转Map简写,保留最后一个key对应的value。
        // 如果key重复会报错,Duplicate key。
        Map<String, User> stringUserMap02 = list.stream().collect(Collectors.toMap(User::getName, v -> v));
        System.out.println(stringUserMap02);

        // List转Map简写,保留最后一个key对应的value。
        // 如果key重复会报错,Duplicate key。
        Map<String, User> stringUserMap03 = list.stream().collect(Collectors.toMap(User::getName, Function.identity()));
        System.out.println(stringUserMap03);
    }

    /**
     * List转List
     * @param list
     */
    public static void test02(List<User> list) {
        // 选择List中所有对象的某一个属性值作为一个新List
        List<String> collect = list.stream().map(User::getName).collect(Collectors.toList());
        System.out.println(collect);
    }

    public static void test01(List<User> list) {
        User user5 = new User(5, "tom5", 15, "t5");
        list.add(user5);
        // filter 过滤为true的值
        list.stream()
                // 过滤为true的值
                .filter(v -> v.id > 2)
                // 通过id排序倒序
                .sorted(User::compareTo)
                // 只输出前两个
                .limit(2)
                .forEach(System.out::println);
    }

    @Data
    static class User implements Comparable<User> {
        private Integer id;
        private String name;
        private Integer age;
        private String addr;

        public User(Integer id, String name, Integer age, String addr) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.addr = addr;
        }

        @Override
        public int compareTo(User o) {
            return o.id - this.id;
        }
    }
}

3.Optional判空

public class OptionDemo {

    public static void main(String[] args) {
        demo01();
    }

    public static void demo01() {
        User user1 = null;
        // User1为空抛出异常
        Optional.ofNullable(user1).orElseThrow(() -> new RuntimeException("user is null"));
        // User1为空就返回一个新的User
        User user3 = Optional.ofNullable(user1).orElse(new User());
        // User1为空就返回一个新的User
        User user4 = Optional.ofNullable(user1).orElseGet(User::new);
        

        User user2 = new User();
        // User2不为空将User2的id设置为10
        Optional.ofNullable(user2).ifPresent(user -> user.id = 10);
        System.out.println(user2.id);

        // User2不为空,输出user2 is not null
        if (Optional.ofNullable(user2).isPresent()) {
            System.out.println("user2 is not null");
        }
    }

    static class User {
        Integer id;
        
        public User() {}
        
        public User(Integer id) {
            this.id = id;
        }
    }
}

4.Double精度损失

/**
     * double直接转BigDecimal会出现精度损失的问题,
     * 可以使用Double.toString(d3)或者如果是Double类型可以使用Double.toString();
     */
public static void doubleDemo() {
    double d1 = 12.49;
    BigDecimal decimal = new BigDecimal(d1);
    // 会出现精度损失。12.4900000000000002131628207280300557613372802734375
    System.out.println(decimal);

    Double d2 = 12.49;
    // 12.49
    decimal = new BigDecimal(d2.toString());
    System.out.println(decimal);

    double d3 = 12.49;
    decimal = new BigDecimal(Double.toString(d3));
    // 12.49
    System.out.println(decimal);
}

5.BigDecimal

public static void test13() {
    BigDecimal b1 = new BigDecimal("1.0");
    BigDecimal b2 = new BigDecimal("1");

    System.out.println(b1.equals(b2)); // false
    System.out.println(b1.compareTo(b2)); // 0,相等。

    BigDecimal b3 = new BigDecimal("1E11");
    // 有必要时使用科学计数法
    System.out.println(b3.toString()); // 1E+11
    // 不使用任何指数(永不使用科学计数法)
    System.out.println(b3.toPlainString()); // 100000000000
    // 有必要时使用工程计数法。工程记数法是一种工程计算中经常使用的记录数字的方法,与科学计数法类似,但要求10的幂必须是3的倍数
    System.out.println(b3.toEngineeringString()); // 100E+9

    // stripTrailingZeros,去掉尾部不需要的零
    BigDecimal b4 = new BigDecimal("1.000");
    System.out.println(b4.stripTrailingZeros()); // 1

    BigDecimal b5 = new BigDecimal("2.005");
    // 四舍五入
    System.out.println(b5.setScale(2, RoundingMode.HALF_UP)); // 2.01
    // 银行家舍入法,主要在美国使用,四舍六入,五分两种情况,如果前一位为奇数,则入位,否则舍去。
    System.out.println(b5.setScale(2, RoundingMode.HALF_EVEN)); // 2.00
}
posted @ 2021-11-21 19:39  行稳致远方  阅读(34)  评论(0)    收藏  举报