java8新特性

java8新特性

Lambda表达式

为什么要用lambda表达式??

优化代码

没有lambda表达式之前

//添加数据
List<Employee> employeeList = Arrays.asList(
            new Employee("张三",20,5555.55),
            new Employee("李四",34,6666.55),
            new Employee("王五",25,7777.55),
            new Employee("法外狂徒",19,4444.55),
            new Employee("法内狂徒",30,8888.55)
            );


    /**
     * 需求,找出年龄大于30岁的员工
     */
    @Test
    public void test1(){
        List<Employee> employeeList = findAge(this.employeeList);
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }

    }

    public List<Employee> findAge(List<Employee> employees){
        ArrayList<Employee> list = new ArrayList<>();
        for (Employee employee : employees) {
            if(employee.getAge() >= 30){
                list.add(employee);
            }
        }
        return list;
    }

优化方式一: 采用策略模式

//新写个方法
public List<Employee> findAge2(List<Employee> employees,PredicateEmpliyee predicateEmpliyee){
        ArrayList<Employee> arrayList = new ArrayList<Employee>();
        for (Employee employee : employees) {
            if(predicateEmpliyee.test(employee)){
                arrayList.add(employee);
            }
        }
        return arrayList;

    }

//优化1 采用策略模式 建一个接口

package com.hy.lambda;

public interface PredicateEmpliyee<T> {
    public boolean test(Employee employees);
}


//编写接口的实现类

package com.hy.lambda;

public class FindEmployeeAge implements PredicateEmpliyee<Employee> {

    @Override
    public boolean test(Employee employees) {
        return employees.getAge() >= 30;
    }
}


//使用
// 将实现类传入到方法中去
@Test
    public void test2(){
        List<Employee> employeeList = findAge2(this.employeeList, new FindEmployeeAge());
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
    }

优化方式二: 采用匿名内部类

/**
     * 方式二: 使用匿名内部类 策略模式 每次搜需要写一个实现类,太麻烦了
     * 这样就不要每次都去写实现类了
     */
    @Test
    public void test3(){
        List<Employee> employeeList = findAge2(this.employeeList, new PredicateEmpliyee() {
            @Override
            public boolean test(Employee employees) {
                return employees.getAge() >= 30;
            }
        });
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
    }

优化方式三:采用lambda表达式

    /**
     * 方式三 lambda表达式
     * 将前面的实现类的方式和匿名内部类的方式 直接采用lambda表达式去实现
     */
    @Test
    public void test4(){
        List<Employee> employeeList = findAge2(this.employeeList, e -> e.getAge() >= 30);
        employeeList.forEach(System.out::println);
    }

方式四: 使用stream() API 一行代码解决

    /**
     * 方式四 stream API
     */
    @Test
    public void test5(){
        this.employeeList.stream()
                .filter(e -> e.getAge() >= 30)
                .forEach(System.out::println);
    }

java内置四大核心函数式接口

在这里插入图片描述

/**
 * java中内置的四大函数式接口
 *
 * Consumer<T> : 消费型接口
 *      void accept(T t); 可以用于处理一些不需要返回值的需求
 *
 * Supplier<T> : 供给型接口
 *      T get(); 用于一些传递参数进来处理然后返回结果
 *
 * Function<T,R> : 函数型接口
 *      R apply(T t);
 *
 * Predicate<T> : 断言型接口
 *      boolean test(T t);
 *
 *
 */

例子

    /**
     * 消费型接口 Consumer
     */
    public void happy(double money , Consumer<Double> consumer){
        consumer.accept(money);
    }

    @Test
    public void test1(){
        happy(100.00,(m) -> {
            System.err.println("本次共使用"+m);
        });
    }


    /**
     * 供给型接口 Supplier
     */
    public List<Integer> genList(int num, Supplier<Integer> supplier){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = supplier.get();
            list.add(n);
        }
        return list;
    }

    @Test
    public void test2(){
        List<Integer> genList = genList(5, () -> (int) (Math.random() * 100));
        for (Integer integer : genList) {
            System.out.println(integer);
        }
    }

    /**
     * 函数型接口 Function
     */
    public String strHandler(String str, Function<String,String> function){
        return function.apply(str);
    }

    @Test
    public void test3(){
        String strHandler = strHandler(" \t\t\t 啊哈哈哈哈哈", (e) -> e.trim());
        System.out.println(strHandler);
    }

    /**
     * 断言型接口 Predicate
     */
    public List<String> filterStr(List<String> strList, Predicate<String> predicate){
        List<String> list = new ArrayList<>();
        for (String s : strList) {
            if(predicate.test(s)){
                list.add(s);
            }
        }
        return list;
    }

    @Test
    public void test4(){
        List<String> list = Arrays.asList("supplier", "function", "consumer", "predicate");
        System.err.println(filterStr(list, (e) -> e.length() > 8));
    }

方法引用和构造器引用

  • 在函数式接口中已经存在的方法可以使用方法引用

  • 如果该函数式接口中存在与lambda体中同样类型参数和返回值的时候,就可以使用方法引用

方法引用

对象::实例方法名

//对象::实例方法名
    @Test
    public void test1(){
        //使用lambda表达式表示
        Consumer<String> con = (e) -> System.out.println(e);
        //使用方法引用表示
        Consumer<String> con2 = System.out::println;
        con.accept("11111");
        con2.accept("22222");
    }

类::静态方法名

//类:静态方法名
    @Test
    public void test2(){
        //compare方法和Comparator接口中的抽象方法的返回值和参数一致
        Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
        com.compare(1,2);

        Comparator<Integer> com2 = Integer::compareTo;
        System.out.println(com2.compare(2, 2));
    }

类::实例方法名

//类:实例方法名
    @Test
    public void test3(){

        BiPredicate<String,String> bp = (str1,str2) -> str1.equals(str1);

        BiPredicate<String,String> bp2 = String::equals;
        System.err.println(bp2.test("wooow", "444"));

    }

构造器引用

  • 构造器引用匹配的是与函数式接口中抽象方法的返回值类型和参数列表相同的构造器

实例对象::new

//构造器引用
    @Test
    public void test4(){
        Supplier<Employee> con = () -> new Employee();

        //在lambda表达式中的构造器引用 返回的是与函数式接口相匹配的构造器
        Supplier<Employee> con2 = Employee::new;
        System.out.println(con2.get());
    }

强大的Stream流

  • 流(Stream)到底是什么?

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

注意

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

Stream创建的四种方式

    //Stream创建的四种方式
    @Test
    public void test1(){
        //第一种方式 使用Collection系列的集合提供的stream()(串行)或parallelStream(并行)进行创建
        List<Integer> arrayList = new ArrayList<Integer>();
        arrayList.stream();

        //第二种方式 通过Arrays中的stream()静态方法进行创建
        Employee[] employeeList = new Employee[10];
        Arrays.stream(employeeList);

        //第三种方式 通过Stream类中的静态方法of
        Stream.of("aa","bb","cc");

        //第四种方式 创建无限流 使用迭代器创建无限流
        Stream.iterate(0,(a) -> a+2).limit(10).forEach(System.out::println);

        Stream.generate(() -> Math.random()).limit(10).forEach(System.out::println);

    }
使用stream进行筛选与切片
/**
     * 使用stream进行筛选与切片
     * filter(Predicate pd) 排除某些元素,过滤
     * distinct 筛选去除重复元素
     * limit 截断流 获取流中给定个数
     * skip 截取掉 与limit相反
     */
    @Test
    public void test1() {
        //filter(Predicate pd) 排除某些元素,过滤
        employeeList.stream()
                .filter(e -> e.getAge() > 21)
                .forEach(System.out::println);

        System.out.println("---------------------------");

        //distinct 筛选去除重复元素
        employeeList.stream()
                .distinct()
                .forEach(System.out::println);

        System.out.println("---------------------");
        //limit 截断流 获取流中给定个数
        employeeList.stream()
                .limit(2)
                .forEach(System.out::println);
        System.out.println("---------------------");

        //limit 截断流 获取流中给定个数 截取掉 与limit相反
        employeeList.stream()
                .skip(2)
                .forEach(System.out::println);
    }

在这里插入图片描述

映射
    /**
     * 映射
     * map 接收一个函数参数,该函数会被应用到每个元素上  将每个元素映射成一个新的元素
     * mapToDouble 可以将每个元素都转换成double类型
     */
    @Test
    public void test2(){
        //map 接收一个函数参数,该函数会被应用到每个元素上  将每个元素映射成一个新的元素
        employeeList.stream()
                .map(Employee::getName)
                .forEach(System.out::println);

        System.out.println("---------------------");

        //  mapToDouble 可以将每个元素都转换成double类型
        employeeList.stream()
                .mapToDouble(Employee::getAge)
                .forEach(System.out::println);

        System.out.println("---------------------");

        //mapToInt 可以将每个元素都转换成int类型
        employeeList.stream()
                .mapToInt(e -> (int) e.getSalary())
                .forEach(System.out::println);

    }

在这里插入图片描述

查找与匹配
 /**
     * 查找与匹配
     * allMatch 检查是否匹配所有元素
     */
    @Test
    public void test3(){
        //allMatch 检查是否匹配所有元素
        boolean b = employeeList.stream()
                .allMatch(e -> "info".equals(e.getStatus()));
        System.out.println(b);

        System.out.println("-------------------");

        //anyMatch 检查是否匹配单个元素
        boolean b1 = employeeList.stream()
                .anyMatch(e -> "info".equals(e.getStatus()));
        System.out.println(b1);
        System.out.println("-------------------");

        //noneMatch 检查没有匹配到元素
        boolean b2 = employeeList.stream()
                .noneMatch(e -> "asdas".equals(e.getStatus()));
        System.out.println(b2);

        System.out.println("-------------------");
        //返回第一个元素
        Optional<Employee> first = employeeList.stream()
                .findFirst();
        System.out.println(first);

        System.out.println("-------------------");
        //返回当前流中的任意元素
        Optional<Employee> any = employeeList.stream()
                .sorted((x,y) -> Integer.compare(x.getAge(),y.getAge()))
                .findAny();
        System.out.println(any);

    }

在这里插入图片描述

排序
/**
     * 排序
     *sorted() 按照自然顺序进行排序
     * sorted(Comparator com ) 按照比较器的顺序进行排序
     */
    @Test
    public void test4(){
        List<Integer> integers = Arrays.asList(1, 5, 8, 7, 1, 2);
        integers.stream()
                .sorted()
                .forEach(System.out::println);

        employeeList.stream()
                .sorted((x,y) -> Integer.compare(x.getAge(),y.getAge()))
                .forEach(System.out::println);
    }

在这里插入图片描述

归约和收集

归约

/**
     * 归约
     * reduce(T t,BinaryOperator) 第一个值是起始值
     * reduce(BinaryOperator)
     */
    @Test
    public void test5(){
        //计算工资总和 map-reduce
        Double reduce = employeeList.stream()
                .map(Employee::getSalary)
                .reduce(0.00, (x, y) -> x + y);
        System.out.println(reduce);

        System.out.println("-------------------");

        Optional<Double> reduce1 = employeeList.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(reduce1);


    }

在这里插入图片描述

收集

/**
 * 收集
 * collect() 参数中可以传Collectors
 */
@Test
public void test6(){
    //将名称取出来再加入到一个集合中去
    List<String> list = employeeList.stream()
            .map(Employee::getName)
            .collect(Collectors.toList());
    System.out.println(list);

    System.out.println("----------------------");

    //找出年龄最大的元素
    Optional<Employee> collect = employeeList.stream()
            .collect(Collectors.maxBy((x, y) -> Integer.compare(x.getAge(), y.getAge())));
    System.out.println(collect);

    System.out.println("----------------------");

    // summarizingDouble 找出集合中该字段的总条数、总和、最小值、最大值、平均值
    DoubleSummaryStatistics collect1 = employeeList.stream()
            .collect(Collectors.summarizingDouble(Employee::getSalary));
    System.out.println(collect1);
    System.out.println(collect1.getMax());
    System.out.println(collect1.getAverage());

    System.out.println("----------------------");

    //joining 将取出的元素用指定的符号进行分割 并设置前缀和后缀
    String collect2 = employeeList.stream()
            .map(Employee::getName)
            .collect(Collectors.joining(",","==","zz"));
    System.out.println(collect2);
}

在这里插入图片描述

Optional

从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。

本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。

参考文档https://www.cnblogs.com/zhangboyu/p/7580262.html

public static void main(String[] args) {
        String name = "a";
        //明确对象不为 null  的时候使用 of() of对象为null时会NullPointerException
        Optional<String> opt = Optional.of(name);
        //System.out.println(opt.get());
        //如果对象即可能是 null 也可能是非 null,你就应该使用 ofNullable() 方法
        Optional<String> opt2 = Optional.ofNullable(name);
        //从 Optional 实例中取回实际值对象的方法之一是使用 get() 方法
        //System.out.println(opt2.get());
        //这个方法会在值为 null 的时候抛出异常。要避免异常,你可以选择首先验证是否有值
        //验证是否有值 isPresent() ifPresent(Consumer<T>)
        opt2.isPresent();
        opt2.ifPresent(e -> System.out.println("a".equals(name)));
        //Optional 类提供了 API 用以返回对象值,或者在对象为空的时候返回默认值。
        // orElse 和 orElseGet 区别
        //判断条件有值时
        /**
         * orElse
         * new VO--
         * orElseGet
         * orElse执行了orElse里面的为空时的条件
         * orElseGet只执行了不为空的条件
         */
        HomeVo homeVo = new HomeVo();
        homeVo.setHome_id(1);
        homeVo.setChinese_name("1号");
        System.out.println("orElse");
        Optional.ofNullable(homeVo).orElse(SkcssApplicationTests.createVo());
        System.out.println("orElseGet");
        Optional.ofNullable(homeVo).orElseGet(() -> SkcssApplicationTests.createVo());

        /**
         *
         * Java 9 增强
         * Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。
         * or<Supplier<Optional>> homeVo对象为空时才会执行
         * ifPresentOrElse(Consumer<T>,Runnable<T>) homeVo不为空执行Consumer,否则执行Runnable
         * ifPresentOrElse() 方法需要两个参数:一个 Consumer 和一个 Runnable。如果对象包含值,会执行 Consumer 的动作,否则运行 Runnable。
         */
        Optional.ofNullable(homeVo).or(() -> Optional.of(new HomeVo())).get();
        Optional.ofNullable(homeVo).ifPresentOrElse(e -> new HomeVo(),() -> System.out.println("runnable"));

    }

    public static HomeVo createVo(){
        System.out.println("new VO--");
        return new HomeVo();
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值