Java8为什么引入Lambda表达式
2017-12-08 10:08
471 查看
Lambda和Stream是Jdk1.8中引入的两个重要特性,大家都知道Lambda是函数式编程,可以将方法像参数一样传递,那么什么是Lambda表达式呢,我们一起来看一下。
首先我们定义一个员工类Employee,他含有三个字段name,age和salary。代码如下
我们要获取出员工中年龄大于25岁的员工该怎么做?传统的代码如下:他首先初始化了一个新的List,然后循环遍历传来的参数,将符合条件的放入结果集中。这段代码有用的就emp.getAge()>=25这一句。
如果我们想将条件改为工资大于10000的该怎么做呢?同样的思路将条件改为emp.getSalary()>10000即可。
优化方式一:使用策略设计模式
我们定义一个范型接口MyPredicate<T>,它只有一个方法boolean test(T t),返回值是一个布尔类型,用来做判断。
我们可以使用策略模式,将它作为一个参数传入类似于Comparator接口。
针对不同的功能需求,我们可以使用不同的实现类去实现接口,比如对工资进行判断和对年龄进行判断
然后将实现类传递给策略函数即可:
优化方式二:使用匿名内部类
这两种方式都能很好的解决问题,但是我们在实现接口的时候仍然需要创建实现类和匿名内部类。其中有大量的代码冗余。现在我们来看看Lambda表达式如何来解决这个问题。
是不是感觉到非常简洁!
我们来看一下Lambda表达式的基础语法:Java8中引入了一个新的操作符:"->"该操作符称为箭头操作符或Lambda操作符
箭头操作符将Lambda表达式拆分为两部分:
左侧为Lambda表达式的参数列表
右侧为Lambda表达式所需执行的功能,即Lambda体
Lambda是对接口的实现,试想如果有多个具有相同参数的接口我们知道要实现哪一个么?所以我们需要函数式接口——只有一个函数的接口
Lambda语法规则:
语法格式一:无参数,无返回值
语法格式二:一个参数,并且无返回值,且只有一个参数时,小括号可以忽略不写(最好还是写上,不然看起来很困难)
语法格式三:两个以上参数,有返回值,且Lambda体中有多条语句,这时需要用{}将Lambda体包括起来
语法格式四:若Lambda体中只有一条语句,return和大括号都可以忽略不写
语法格式五:Lambda表达式的参数列表的数据类型可以忽略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”
Lambda表达式需要“函数式接口”的支持
函数式接口就是接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface修饰可以检查是否是函数式接口
首先我们定义一个员工类Employee,他含有三个字段name,age和salary。代码如下
public class Employee { private String name; private int age; private double salary; public Employee(String name, int age, double salary) { super(); this.name = name; this.age = age; this.salary = salary; } }
我们要获取出员工中年龄大于25岁的员工该怎么做?传统的代码如下:他首先初始化了一个新的List,然后循环遍历传来的参数,将符合条件的放入结果集中。这段代码有用的就emp.getAge()>=25这一句。
public List<Employee> filterEmployees(List<Employee> list) { List<Employee> emps = new ArrayList<>(); for (Employee emp : list) { if (emp.getAge() >= 25) { emps.add(emp); } } return emps; }
如果我们想将条件改为工资大于10000的该怎么做呢?同样的思路将条件改为emp.getSalary()>10000即可。
public List<Employee> filterEmployees2(List<Employee> list) { List<Employee> emps = new ArrayList<>(); for (Employee emp : list) { if (emp.getSalary() >= 5000) { emps.add(emp); } } return emps; }可以看到,有大段的代码重复,只有中间改了一句话是有效的,那么我们要如何改进呢?
优化方式一:使用策略设计模式
我们定义一个范型接口MyPredicate<T>,它只有一个方法boolean test(T t),返回值是一个布尔类型,用来做判断。
public interface MyPredicate<T> { public boolean test(T t); }
我们可以使用策略模式,将它作为一个参数传入类似于Comparator接口。
public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp) { List<Employee> emps = new ArrayList<>(); for (Employee employee : list) { if (mp.test(employee)) { emps.add(employee); } } return emps; }
针对不同的功能需求,我们可以使用不同的实现类去实现接口,比如对工资进行判断和对年龄进行判断
public class FilterEmployeeByAge implements MyPredicate<Employee>{ @Override public boolean test(Employee t) { return t.getAge()>=25; } }
public class FilterEmployeeBySalary implements MyPredicate<Employee>{ @Override public boolean test(Employee t) { return t.getSalary()>=10000; } }
然后将实现类传递给策略函数即可:
List<Employee> list= filterEmployee(employees, new FilterEmployeeByAge()); List<Employee> list2 = filterEmployee(employees, new FilterEmployeeBySalary());
优化方式二:使用匿名内部类
public void test() { List<Employee> list = filterEmployee(employees, new MyPredicate<Employee>() { @Override public boolean test(Employee t) { // TODO Auto-generated method stub return t.getSalary() <= 50000; } }); for (Employee employee : list) { System.out.println(employee); } }
这两种方式都能很好的解决问题,但是我们在实现接口的时候仍然需要创建实现类和匿名内部类。其中有大量的代码冗余。现在我们来看看Lambda表达式如何来解决这个问题。
public void test() { List<Employee> list = filterEmployee(employees, (e) -> e.getSalary() <= 5000); list.forEach(System.out::println); }
是不是感觉到非常简洁!
我们来看一下Lambda表达式的基础语法:Java8中引入了一个新的操作符:"->"该操作符称为箭头操作符或Lambda操作符
箭头操作符将Lambda表达式拆分为两部分:
左侧为Lambda表达式的参数列表
右侧为Lambda表达式所需执行的功能,即Lambda体
Lambda是对接口的实现,试想如果有多个具有相同参数的接口我们知道要实现哪一个么?所以我们需要函数式接口——只有一个函数的接口
Lambda语法规则:
语法格式一:无参数,无返回值
Runnable r = () -> System.out.println("Hello world"+num); r.run();
语法格式二:一个参数,并且无返回值,且只有一个参数时,小括号可以忽略不写(最好还是写上,不然看起来很困难)
Consumer<String> con=x -> System.out.println(x); con.accept("lemon go!");
语法格式三:两个以上参数,有返回值,且Lambda体中有多条语句,这时需要用{}将Lambda体包括起来
Comparator<Integer> com=(x,y)->{ System.out.println("函数式接口"); return Integer.compare(x, y); };
语法格式四:若Lambda体中只有一条语句,return和大括号都可以忽略不写
Comparator<Integer> com1=(Integer x,Integer y)->Integer.compare(x, y);
语法格式五:Lambda表达式的参数列表的数据类型可以忽略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”
(Integer x,Integer y)->Integer.compare(x, y);
Lambda表达式需要“函数式接口”的支持
函数式接口就是接口中只有一个抽象方法的接口,称为函数式接口。可以使用注解@FunctionalInterface修饰可以检查是否是函数式接口
相关文章推荐
- Java 8为什么需要Lambda表达式
- Java 8为什么需要Lambda表达式
- Java 8为什么需要Lambda表达式
- Java 8 lambda表达式引入详解及实例
- Java 8 习惯用语,第 6 部分 为什么完美的 lambda 表达式只有一行
- Java 8为什么需要Lambda表达式
- [FAQ]为什么引入lambda表达式
- 在Android中引入Java8的lambda表达式
- java lambda表达式
- 探索Java语言与JVM中的Lambda表达式
- JAVA8之lambda表达式详解,及stream中的lambda使用
- Java8初体验(一)lambda表达式语法
- java8的lambda表达式
- JAVA Lambda表达式
- Java 8 Lambda表达式探险
- Java 8之Lambda表达式
- JAVA 8 Lambda表达式-Lambda Expressions
- java中Lambda表达式的用法
- java8新特性--lambda表达式
- Java新特性-Lambda表达式入门