定义

​ jdk8发布新特性中,lambda是一大亮点之一。lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率。Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包。如果你之前了解scala和js函数式编程,将会更加快速上手和学习java8的lambda新特性。

语法

​ Lambda表达式在Java8中引入了一个新的语法操作符号,即:->,它将Lambda表达式分为两部分。

(parameters) -> expression
或
(parameters) ->{ statements; }
  1. 无参数

    // java 8之前的写法
    Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " >---Lambda");}
    };
    // 使用lambda的写法
    Runnable r = () -> System.out.println(Thread.currentThread().getName() + " >---Lambda");
  2. 一个参数的使用

    // java 8 之前的写法
    Consumer<String> consumer = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};// Lambda表达式的写法
    Consumer<String> consumer = (par)->System.out.println(par);
    consumer.accept("xixi");
    一个参数的小括号可以省略,简化如下:
    Consumer<String> consumer = par->System.out.println(par);
  3. 三个参数的使用

    // java 8之前的写法
    Comparator<Integer> comparator = new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o1.compareTo(o2);}};// 使用Lambda表达式的方法 ,当只有一条语句的时候,大括号和return都可以省略Comparator<Integer> comparator=(x,y) -> x.compareTo(y);

注意:如何推断出是哪个方法的?

很简单是类型推断的作用,java8中有个很大的变化,就是类型推断,简单来说javac在编译代码时候,会根据程序的上下文来推断出Lambda表达式参数类型,从而根据参数类型和个数判断出是该类的哪个方法。

例如

Comparator<Integer> comparator=(x,y) -> x.compareTo(y);

这里在编译的时候,在执行x.compareTo(y)的时候根据类型推断,因为这个接口定义数据的泛型是Intger,所以根据类型推断会自动调用Integer.compareTo方法。

需求

王小明所在的公司,每一个月都会进行薪资财务报表,王小明每一个月都会自己对员工们的薪资做统计,以了解公司财务支出和订单提成等需求。常常有做订单提成排名和总工资排名的这样的一个需求。
我们将定义以下类,来完成王小明的统计需求。

  • 基本员工类
package com.codegeek.lambda;
import lombok.*;@Setter
@Getter
@NoArgsConstructor
@ToString
public class Employee {/*** 员工姓名*/private String name;/*** 员工年龄*/private int age;/*** 基本薪水*/private double basicSalary;/*** 订单成交总额*/private double dealTotalPrice;public Employee(String name, int age, double basicSalary,double dealTotalPrice) {this.name = name;this.age = age;this.basicSalary = basicSalary;this.dealTotalPrice = dealTotalPrice;}/*** 员工总薪资** @return Double*/public Double getTotalSalary() {return this.basicSalary + this.dealTotalPrice * 0.04;}
}

​ 现在假设在A部门有,青龙,白虎,朱雀,玄武 四个部门人员。下面是他们上个月基本薪资的情况。

Employee qingLong = new Employee("青龙", 25, 5500, 7500);
Employee baiHu = new Employee("白虎", 27, 5000, 9000);
Employee zhuQue = new Employee("朱雀", 22, 3800, 4500);
Employee xuanWu = new Employee("玄武", 24, 3300, 3300);
List<Employee> employees = Arrays.asList(qingLong, baiHu, zhuQue, xuanWu);

​ 现在有个统计的需求是,按员工年龄从小到大排列,并获取员工姓名列表。让我们分别使用Lambda表达式和java8之前的做法。

// 员工列表先进行排序
employees.sort(new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {Integer age1 = o1.getAge();Integer age2 = o2.getAge();return age1.compareTo(age2);}
});
// 遍历排序后的列表并输出员工姓名for (Employee employee : employees) {System.out.println(employee.getName());}
  • 使用Lambda的做法
employees.stream().sorted((o1, o2) -> o1.getAge().compareTo(o2.getAge()))
.forEach(o -> System.out.println(o.getName()));

函数式接口

​ 只包含一个抽象方法的接口,称为函数式接口。使用Lambda表达式创建该对象接口的对 象,如果Lambda抛出一个受检异常,通常需要在目标接口使用@FunctionalInterface注解,来声明标记了该注解的接口是一个函数式接口。

  • java常用4个自带的函数式接口

    函数式接口 参数类型 返回类型 使用说明
    Consumer 消费型接口 T void 对类型T的数据进行操作,抽象方法 void accept(T t)
    Supplier 供给型接口 T 返回类型T的对象,抽象方法 T get();
    Function<T,R>函数型接口 T R 对类型T对象进行操作,返回类型R的对象,抽象方法R apply(T t)
    Predicate断言式接口 T boolean 对类型T对象进行操作,返回类型boolean,抽象方法boolean test(T t)
  • 四大函数式接口的使用

public class FourFunctionsTest {// 消费式接口@Testpublic void testConsumer() {Consumer<Integer> consumer = x -> System.out.println(x);consumer.accept(1);}// 供给式接口@Testpublic void testSupplier() {Supplier<String> supplier = () -> {StringBuffer sb = new StringBuffer();return sb.append("我").append(520).append("you").toString();};System.out.println(supplier.get());}// 断言式接口@Testpublic void testPredicate() {Predicate<Long> predicate = x -> x == 1L;System.out.println(predicate.test(2L));}// 函数式接口@Testpublic void testFunction() {Function<Integer, Boolean> function = x -> x > 3;System.out.println(function.apply(4));}
}
  • 自定义函数式接口

    // 使用策略式接口
    @FunctionalInterface // 函数式接口(检查)只能有一个抽象方法
    public interface MyFilter<T> {/*** 获取指定想要的employee对象** @param t* @return*/boolean getWant(T t);
    }/*** 策略设计模式*/
    public List<Employee> needEmployee(List<Employee> employeeList, MyFilter<Employee> filter) {List<Employee> employees = new ArrayList<>();for (Employee employee : employeeList) {if (filter.getWant(employee)) {employees.add(employee);}}return employees;});
    // 使用策略者设计模式Lambda简化
    needEmployee(employees, employee -> mployee.getTotalSalary() >= 5000);
    

更加简化版(以后会详细讲):

employees.stream().filter(e -> e.getTotalSalary() > 5000d).map(Employee::getName).forEach(System.out::println);

方法引用

使用操作符::将方法名和对象或者类的名字分隔开,组合有以下三种。

  1. 对象::实例方法名
  2. 类::静态方法
  3. 类::实例方法

例如:常见的x-> System.out.println() 等同于System.out::println。

**注意 **

  1. Lambda 体中调用方法的参数列表与返回值类型,要与函数式接口抽象方法的该函数列表和返回值类型保持一致。
  2. 若Lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时。可以使用 ClassName :: method
// 对象::实例方法@Testpublic void testConsumer() {Employee emp = new Employee();// 函数式接口Supplier是空参,返回是Integer类型的接口,// 而对应emp的实例方法getAge()刚刚好是空参且返回Integer类型的数据,符合上面注意事项1的要求Supplier<Integer> supplier = () -> emp.getAge();Supplier<Double> sup2 = emp::getSalary;System.out.println(supplier.get());}// 类::方法名@Testpublic void testSupplier() {Comparator<String> comparator = (x, y) -> x.compareTo(y);// 要求参数第一个值作为方法体的调用者,第二个参数值作为方法体的被调用者(参数)符合注意事项2的要求Comparator<String> compString = String::compareTo;System.out.println(comparator.compare("2", "3"));Comparator<Integer> com = Integer::compare;System.out.println(com.compare(1, 2));BiPredicate<String, String> predicate = String::equals;System.out.println(predicate.test("we", "eq"));}

构造器引用

这儿以函数式接口为例:可以将返回的参数R,使用构造器的构造方法。

// 当Employee有下面的构造时候public Employee(int age) {this.age = age;}

可以构造下面这样一个函数式接口:

Function<Integer,Employee> fun = i -> new Employee(i)
System.out.println(fun.apply(13));// 使用构造器引用简化后:
Function<Integer,Employee> fun = Employee::new
System.out.println(fun.apply(15));

java8新特性lambda表达式概述相关推荐

  1. Java8新特性----Lambda表达式详细探讨

    Java8新特性 Lambda表达式 入门演示 案例1 如何解决 cannot be cast to java.lang.Comparable问题? 案例2 优化方式一 : 策略设计模式 优化方式二: ...

  2. java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量

    一提到java是一种什么语言? 大多数人肯定异口同声的说是一门面向对象的语言,这种观点从我们开始学java就已经根深蒂固了,但是学到java8新特性函数式编程的时候,我才知道java并不是纯面向对象的 ...

  3. java8新特性-lambda表达式入门学习

    定义 jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expressi ...

  4. Java8新特性——lambda表达式

    什么是lambda表达式? Lambda 表达式是Java 8 的新特性,是一种新的编程语法.lambda语义简洁明了,性能良好,是Java 8 的一大亮点.废话不多说,我们来看个例子. 从内部类到l ...

  5. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  6. java compare 返回值_关于Java你不知道的那些事之Java8新特性[Lambda表达式和函数式接口]...

    前言 为什么要用Lambda表达式? Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码,将代码像数据一样传递,这样可以写出更简洁.更灵活的代码,作为一个更紧凑的代码风 ...

  7. 2020.10.20课堂笔记(java8新特性 lambda表达式)

    一.什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个"值". 如果你想把"一块代码"赋给一个Java变量,应该怎么做呢? 比如,我想把右 ...

  8. Java8 新特性 -- Lambda表达式:函数式接口、方法的默认实现和静态方法、方法引用、注解、类型推测、Optional类、Stream类、调用JavaScript、Base64

    文章目录 1. Lambda表达式 1.1 Lambda表达式语法 1.2 Lambda表达式示例 1.3 说明:函数式接口 2. 方法的默认实现和静态方法 3. 方法引用 3.1 方法引用示例 4. ...

  9. Java8 新特性lambda表达式(一)初始

    本篇参考Richard Warburton的 java8 Lambdas :Functional Programming for the Masses 学习lambda表达式之前,需要知道什么是函数式 ...

最新文章

  1. 如何在GNOME中添加自己的菜单项
  2. Excel表格快速将公式运用到一整列
  3. 财经法规税收征收管理法律制度练习题一
  4. linux:Too Many Open Files(打开的文件过多)
  5. [HAOI2008]移动玩具
  6. DDMMSS.SS转为DD
  7. java class _Java Class文件详解
  8. java(5)---Java基础知识大全
  9. php登录界面模板美化,一款简单好看的登录界面——Typecho美化包 Sign-Page-For-Typecho...
  10. Atitit 提升开发效率 声明式编程范式 目录 1. 声明式编程体系树 1 1.1. 声明式(对比:指令式,,主要包括 函数式,逻辑式编程) 2 1.2. 声明式编程:表达与运行分离 3 1.3
  11. 【PS平面设计教程】6种最常用抠图技巧,十万人都抢着收藏
  12. Servlet实现一个登陆界面
  13. ssl证书申请,springboot部署https
  14. windows server2019安装SQLServer
  15. 洛谷P4207 [NOI2005]月下柠檬树(计算几何+自适应Simpson法)
  16. JS获取跨域的cookie实例
  17. CentOS 7 关于防火墙操作
  18. 一个三线程序员的2020年,CSDN 10 万粉里程碑达成
  19. Django知识点:认识Django
  20. 盘后股价上涨6% 美光能否结束水逆?

热门文章

  1. th:classappend
  2. information security
  3. 360极速浏览器安装谷歌浏览器插件.CRX报CRX_VERSION_NUMBER_INVALID问题的解决
  4. Homogeneous和Heterogeneous区别
  5. C# winfrom 拼接图片
  6. oracle插入数据报ORA-00001:违反唯一约束条件
  7. python调用exe程序mspaint_Python:控制柄mspaint.exe窗口返回0
  8. 预告:今天(6月21日)20点,做客 刘润直播间 聊聊“进化的故事”
  9. 优惠券测试用例分析(移动端)
  10. 重装系统后,如何调用之前mysql的数据