Java8新特性:Lambda表达式


一 Java8新特性简介

============

Java8主要加入了如下几个新特性:

1. Lambda 表达式

2. 函数式接口

3. 方法引用与构造器引用

4. Stream API

5. 接口中的默认方法与静态方法

6. 新时间日期 API

7. 其他新特性

其中最重要的莫过于Lambda表达式和Stream API。本篇博客主要介绍Lambda表达式。

二 案例切入:

=======

员工类pojo:这是Employee类的代码,省略了构造器,getter和setter方法以及重写的hashcode(),equals(),toString()方法等代码

public class Employee {

private int id;

private String name;

private int age;

private double salary;

//空参,全参构造器

//getter,setter方法

//重写hashcode(),equals(),toString()方法

}

然后在集合内添加相应的员工:

List 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)

);

2.1 案例需求1:获取年龄小于35的员工信息


public List filterEmployeeAge(List emps){

List list = new ArrayList<>();

for (Employee emp : emps) {

if(emp.getAge() <= 35){

list.add(emp);

}

}

return list;

}

这是过滤年龄的方法,传入一个元素都是员工的集合,会得到筛选条件为年龄小于等于35的员工集合。

我们可以对filterEmployeeAge方法进行测试。

@Test

public void test3(){

List list = filterEmployeeAge(emps);

for (Employee employee : list) {

System.out.println(employee);

}

}

输出结果如下:

2.2 案例需求2:获取工资大于5000的员工信息


可以仿照filterEmployeeAge方法再写一个按照工资过滤的方法filterEmployeeSalary

public List filterEmployeeSalary(List emps){

List list = new ArrayList<>();

for (Employee emp : emps) {

if(emp.getSalary() >= 5000){

list.add(emp);

}

}

return list;

}

对比filterEmployeeAge和filterEmployeeSalary方法,可以发现这两个过滤方法的代码主要区别就是if()里面的判断条件,符合相应条件的加入集合。如果还有其它的需求:例如姓名长度,性别,部门,工资小于3500,年龄大于60等过滤条件,我们还得再写相应的方法;而这些方法的区别仍是if()里面的判断条件,我们却得写很多重复的代码,增大很多不必要的工作量。

说到这里,很多人就会想到了策略模式就是解决这个问题的。(接下来使用策略模式优化上面的代码,顺便复习一下策略设计模式)

2.3 优化方式1:策略设计模式


将if()里面的判断条件抽取出来作为一个接口。

public interface MyPredicate {

public boolean test(T t);

}

然后,不同的过滤条件封装在MyPredicate接口的实现类中

按年龄过滤条件实现类:

public class FilterEmployeeForAge implements MyPredicate{

@Override

public boolean test(Employee t) {

return t.getAge() <= 35;

}

}

按工资过滤条件实现类:

public class FilterEmployeeForSalary implements MyPredicate {

@Override

public boolean test(Employee t) {

return t.getSalary() >= 5000;

}

}

针对接口写统一的过滤员工方法,不同的过滤条件只需要传入相应的MyPredicate接口实现类即可以。

public List filterEmployee(List emps, MyPredicate mp){

List list = new ArrayList<>();

for (Employee employee : emps) {

if(mp.test(employee)){

list.add(employee);

}

}

return list;

}

测试:

@Test

public void test4(){

List list = filterEmployee(emps, new FilterEmployeeForAge());

for (Employee employee : list) {

System.out.println(employee);

}

System.out.println(“------------------------------------------”);

List list2 = filterEmployee(emps, new FilterEmployeeForSalary());

for (Employee employee : list2) {

System.out.println(employee);

}

}

2.4 优化方式2:匿名内部类


事实上,我们在使用策略模式进行优化的时候,并不会写MyPredicate接口的实现类,而是将MyPredicate接口的匿名内部类作为参数传入filterEmployee方法。

//优化方式二:匿名内部类

@Test

public void test5(){

List list = filterEmployee(emps, new MyPredicate() {

@Override

public boolean test(Employee t) {

return t.getId() <= 3;

}

});

for (Employee employee : list) {

System.out.println(employee);

}

}

2.5 优化方式3:Lambda表达式


说到匿名内部类作为参数传递给方法,就离Lambda表达式非常接近了。Lambda表达式就是对匿名内部类作为参数传递给方法进行优化。

这里先直接给出Lambda表达式优化后的结果,大家可以感受下代码是多么的简洁。

//优化方式三:Lambda 表达式

@Test

public void test6(){

List list = filterEmployee(emps, (e) -> e.getAge() <= 35);

list.forEach(System.out::println);

System.out.println(“------------------------------------------”);

List list2 = filterEmployee(emps, (e) -> e.getSalary() >= 5000);

list2.forEach(System.out::println);

}

2.6 优化方式4:Stream API


这里也是直接给出结果,后续解释。

//优化方式四:Stream API

@Test

public void test7(){

//年龄小于等于35的员工信息

emps.stream()

.filter((e) -> e.getAge() <= 35)

.forEach(System.out::println);

}

三 Lambda表达式语法

=============

Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。

箭头操作符的左侧传递给接口内抽象方法的形参,箭头操作符右侧作为接口内抽象方法的方法体。

3.1 语法:


Lambda 表达式的基础语法:Java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或 Lambda 操作符

箭头操作符将 Lambda 表达式拆分成两部分:

左侧:Lambda 表达式的参数列表

右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体

语法格式一:无参数,无返回值

() -> System.out.println(“Hello Lambda!”);

语法格式二:有一个参数,无返回值

(x) -> System.out.println(x)

语法格式三:若只有一个参数,小括号可以省略不写(为了方便阅读和理解,常常不会省略小括号,即采用语法格式二那样)

x -> System.out.println(x)

语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句(有多条语句就需要大括号,并将多条语句放入其中)

Comparator com = (x, y) -> {

System.out.println(“函数式接口”);

return Integer.compare(x, y);

};

语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写

Comparator com = (x, y) -> Integer.compare(x, y);

语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”

(Integer x, Integer y) -> Integer.compare(x, y);

上联:左右遇一括号省

下联:左侧推断类型省

横批:能省则省

3.2 语法练习


//语法格式一:无参,无返回值

@Test

public void test1(){

int num = 0;//jdk 1.7 前,必须是 final

//创建线程(未使用Lambda表达式)

Runnable r = new Runnable() {

@Override

public void run() {

System.out.println(“Hello World!” + num);

}

};

r.run();

System.out.println(“-------------------------------”);

//使用Lambda表达式

Runnable r1 = () -> System.out.println(“Hello Lambda!”);

r1.run();

}

//语法格式三:一参,无返回值

@Test

public void test2(){

Consumer con = x -> System.out.println(x);

con.accept(“我爱Lambda!”);

}

//语法格式四:两参,有返回值,多条语句

@Test

public void test3(){

Comparator com = (x, y) -> {

System.out.println(“函数式接口”);

return Integer.compare(x, y);

};

}

//语法格式六:类型推断

@Test

public void test4(){

Comparator com = (x, y) -> Integer.compare(x, y);

}

四 Lambda表达式应用

=============

上面仅仅是对Lambda表达式的几种语法进行介绍,接下来将介绍Lambda表达式如何在实际编程中使用。还记得之前案例切入处的一句话吗:Lambda表达式就是对匿名内部类作为参数传递给方法进行优化。

Lambda表达式的作用就是取代_某接口的匿名内部类_作为参数传递给方法。

4.1 应用1:对一个数进行运算


运算方法:operation

//案例1:对一个数进行运算

public Integer operation(Integer num, MyFun mf){

return mf.getValue(num);

}

具体怎么运算运用策略模式的思想封装在MyFun接口中,由MyFun接口的匿名内部类进行具体实现。

public interface MyFun {

public Integer getValue(Integer num);

}

以下是使用匿名内部类和Lambda表达式的对比。

//应用1:对一个数进行运算

@Test

public void test6(){

//匿名内部类

//对该数取平方

Integer num1=operation(100, new MyFun() {

@Override

public Integer getValue(Integer num) {

return num*num;

}

});

System.out.println(num1);

//Lambda表达式

//对该数取平方(一参,有返回值,省略return)

Integer num2 = operation(100, (x) -> x * x);

System.out.println(num2);

//该数加200

System.out.println(operation(200, (y) -> y + 200));

}

4.2 Lambda表达式总结


  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值