zoukankan      html  css  js  c++  java
  • java8:Lambda表达式、函数式接口

    1、

    Comparator接口:

    @FunctionalInterface
    public interface Comparator<T> {
        int compare(T o1, T o2);

    (1)匿名内部类

       @Test
        public void test1() {
            Comparator<Integer> com = new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return Integer.compare(o1, o2);
                }
            };
        }

    (2)Lambda表达式

      @Test
        public void test2(){
            Comparator<Integer> com=(o1,o2)->Integer.compare(o1,o2);
        }

    (3)案例(获取年龄大于35的员工信息)

    常规方式:

    定义一个员工类,遍历所有员工的信息,将年龄大于35的员工的信息存储到新的集合中。但是,如果把需求改为获取工资大于5000的员工信息,只需要改变的是程序的判断条件,这就造成了代码的冗余

    设计模式:策略设计模式

    新建一个员工类

    @Data
    @AllArgsConstructor
    public class Employee {
        private int id;
        private String name;
        private int age;
        private double salary;
    }

    创建一个接口,该接口定义一个用于过滤的方法

    @FunctionalInterface
    public interface MyPredicate<T> {
    
        public boolean test(T t);
        
    }

    创建两个接口的实现类:实现类重写接口的方法分别过滤年龄和工资

    工资

    public class FilterEmployeeForSalary implements MyPredicate<Employee> {
    
        @Override
        public boolean test(Employee t) {
            return t.getSalary() >= 5000;
        }
    
    }

    年龄

    public class FilterEmployeeForAge implements MyPredicate<Employee>{
    
        @Override
        public boolean test(Employee t) {
            return t.getAge() <= 35;
        }
    
    }

    测试类:

    添加员工的信息

    定义过滤方法,该方法的第一个参数是一个Employee类型的List集合,第二个参数是一个接口类型的,也就是说可以传递该接口的所有实现类,也就是说没有将方法写死,方法的灵活度更高了

    第三个方法是测试类,传递员工的信息和接口的实现类,返回的是过滤后的结果

    public class TestLambda {
        List<Employee> emps = Arrays.asList(
                new Employee(101, "张三", 18, 9999.99),
                new Employee(102, "李四", 59, 6666.66),
                new Employee(103, "王五", 28, 3333.33),
                new Employee(104, "赵六", 8, 7777.77),
                new Employee(105, "田七", 38, 5555.55)
        );
    
        public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> myPredicate) {
            List<Employee> employees = new ArrayList<>();
            for (Employee employee : list) {
                if (myPredicate.test(employee)) {
                    employees.add(employee);
                }
            }
            return employees;
        }
    
        @Test
        public void test() {
            List<Employee> employeeList = filterEmployee(emps, new FilterEmployeeForAge());
            for (Employee employee : employeeList) {
                System.out.println(employee);
            }
            System.out.println("-------------------");
            List<Employee> list = filterEmployee(emps, new FilterEmployeeForSalary());
            for (Employee employee : list) {
                System.out.println(employee);
            }
        }

    测试结果:

    Employee(id=101, name=张三, age=18, salary=9999.99)
    Employee(id=103, name=王五, age=28, salary=3333.33)
    Employee(id=104, name=赵六, age=8, salary=7777.77)
    -------------------
    Employee(id=101, name=张三, age=18, salary=9999.99)
    Employee(id=102, name=李四, age=59, salary=6666.66)
    Employee(id=104, name=赵六, age=8, salary=7777.77)
    Employee(id=105, name=田七, age=38, salary=5555.55)

    匿名内部类方式

    public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> myPredicate) {
            List<Employee> employees = new ArrayList<>();
            for (Employee employee : list) {
                if (myPredicate.test(employee)) {
                    employees.add(employee);
                }
            }
            return employees;
        }
    
        @Test
        public void test() {
            List<Employee> list = filterEmployee(emps, new MyPredicate<Employee>() {
                @Override
                public boolean test(Employee employee) {
                    return employee.getSalary() < 7000;
                }
            });
            for (Employee employee : list) {
                System.out.println(employee);
            }
        }

    匿名内部类方式与策略模式相比,少了对实现类的书写,但是匿名内部类的方式还是不够简洁

    Lambda表达式

        public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> myPredicate) {
            List<Employee> employees = new ArrayList<>();
            for (Employee employee : list) {
                if (myPredicate.test(employee)) {
                    employees.add(employee);
                }
            }
            return employees;
        }
    
        @Test
        public void test() {
            List<Employee> list = filterEmployee(emps,(e)->e.getSalary()<7000);
            for (Employee employee : list) {
                System.out.println(employee);
            }
        }

    与函数时接口的方式相比,Lambda表达式的方式使得代码更加简洁

    最简洁的方式:Stream API

      @Test
        public void test() {
            emps.stream()
                    .filter((e)->e.getSalary()>=5000)
                    .forEach(System.out::println);
        }

    此种方式只需要一个实体类

    2、函数式接口

    (1)定义一个函数式接口

    @FunctionalInterface
    public interface MyFun {
    
        public Integer getValue(Integer num);
        
    }

    (2)定义方法并测试

    public class TestLambda {
        public Integer operation(Integer num, MyFun mf) {
            return mf.getValue(num);
        }
    
        @Test
        public void test() {
            Integer num = operation(100, (x) -> x * x);
            System.out.println(num);
    
            System.out.println(operation(200, (y) -> y + 200));
        }
    }

    方法一的参数是一个接口类型的,该方法调用了接口内的方法

    方法二是测试方法,Lambda表达式需要传递一个参数

    3、Lambda表达式的应用

    (1)排序

    函数式接口

    int compare(T o1, T o2);

    调用函数式接口的方法

       public static <T> void sort(List<T> list, Comparator<? super T> c) {
            list.sort(c);
        }

    测试类

        List<Employee> emps = Arrays.asList(
                new Employee(101, "张三", 18, 9999.99),
                new Employee(102, "李四", 59, 6666.66),
                new Employee(103, "王五", 28, 3333.33),
                new Employee(104, "赵六", 8, 7777.77),
                new Employee(105, "田七", 38, 5555.55)
        );
    
        @Test
        public void test1() {
            Collections.sort(emps, (e1, e2) -> {
                if (e1.getAge() == e2.getAge()) {
                    return e1.getName().compareTo(e2.getName());
                } else {
                    return Integer.compare(e1.getAge(), e2.getAge());
                }
            });
    
            for (Employee emp : emps) {
                System.out.println(emp);
            }
        }

    (2)处理字符串

    定义一个函数式接口

    @FunctionalInterface
    public interface MyFunction {
        
        public String getValue(String str);
    
    }

    定义字符串处理方法和测试方法

    public class TestLambda {
        public String strHandler(String str, MyFunction mf){
            return mf.getValue(str);
        }
        @Test
        public void test2(){
            String trimStr = strHandler("   你好   ", (str) -> str.trim());
            System.out.println(trimStr);
    
            String upper = strHandler("qqqqeeeabc", (str) -> str.toUpperCase());
            System.out.println(upper);
    
            String newStr = strHandler("1234556", (str) -> str.substring(2, 5));
            System.out.println(newStr);
        }
    }

    (3)数据处理

    函数值接口

    public interface MyFunction2<T, R> {
    
        public R getValue(T t1, T t2);
    
    }

    测试类

    public class TestLambda {
        public void op(Long l1, Long l2, MyFunction2<Long, Long> mf){
            System.out.println(mf.getValue(l1, l2));
        }
        @Test
        public void test3(){
            op(100L, 200L, (x, y) -> x + y);
    
            op(100L, 200L, (x, y) -> x * y);
        }
    }

    总结

      匿名内部类能够避免接口的实现类的书写,但是还可以通过Lambda表达式进一步简化,Lambda表达式的应用需要借助于函数式接口,JDK中自带的有一些函数式接口,可以拿来直接使用

      Lambda表达式的箭头左边用来书写输入参数,右边是函数式接口方法的实现

  • 相关阅读:
    hdu3457(有向图的dp问题)
    nyoj16矩形嵌套(第一道dp关于dag的题目)
    noj1475(递推题)统计多少个1
    hdu1331(记忆化搜索)
    hdu1142(dj+记忆化搜索)
    hdu1978(记忆化搜索)
    用广搜实现的spfa
    hdu1428(记忆化搜索)
    hdu1078(记忆化搜索)
    poj3261(后缀数组)
  • 原文地址:https://www.cnblogs.com/zhai1997/p/13958240.html
Copyright © 2011-2022 走看看