Lambda是啥?
Lambda 表达式也称为闭包,是 JDK8 的一个新特性,可以取代大部分的匿名内部类,配合stream进行使用在集合的遍历和其他集合操作中,可以极大地优化代码结构。
JDK8 也提供了大量的内置函数式接口供我们使用,使得 Lambda 表达式的运用更加方便、高效。
Lambda如何使用?
基础语法
Java 中的 Lambda 表达式通常使用语法是 (argument) -> (body),比如:
(arg1, arg2...) -> { body }
(type1 arg1, type2 arg2...) -> { body }
以下是 Lambda 表达式的简单示例:
//不需要参数,返回值为10
() -> 10
//接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
//接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
//接收2个int型整数,返回他们的和
(int x, int y) -> x + y
//接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
总结Lambda表达式特征:
- Lambda 表达式可以具有零个,一个或多个参数;
- 可以显式声明参数的类型,也可以由编译器自动从上下文推断参数的类型;
- 一个参数无需定义圆括号,但多个参数需要定义圆括号,并用逗号进行分隔;
- 如果 Lambda 表达式的正文只有一条语句,则大括号可不用写,且表达式的返回值类型要与匿名函数的返回类型相同
使用环境
一种情况是:Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法的接口可以使用Lambda表达式进行实现。
JDK 8中新增的另外一个特性,接口的默认方法:
default,简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个 default 关键字即可实现默认方法。
另外一种情况是:功能接口,即使用注解@FunctionalInterface标注的接口,都可以使用Lambda表达式;这个注解是修饰函数式接口的,要求接口中的抽象方法只有一个。
其实如果你对匿名内部类非常熟悉的话,理解这个就非常容易了,Lambda表达式取代了匿名内部类的书写方式。
Lambda表达式例子
功能接口
当一个接口使用注解
@FunctionalInterface的时候,我们就可以利用Lambda表达式进行调用
package com.mvasoft.lambda.demo;
@FunctionalInterface
public interface WorkerInterface {
public void doWork();
}
class WorkTest {
public static void main(String[] args) {
// 通过匿名内部类调用
WorkerInterface work = new WorkerInterface() {
@Override
public void doWork() {
System.out.println("通过匿名内部类调用");
}
};
work.doWork();
// 通过 Lambda 表达式调用
// Lambda 表达式实际上是一个对象。
// 我们可以将 Lambda 表达式赋值给一个变量,就可像其它对象一样调用。
work = ()-> System.out.println("通过 Lambda 表达式调用");
work.doWork();
}
}
创建线程
线程初始化写法的优化,而且当我们使用idea写代码的时候,如果写出了之前的方式,idea也会自动提示我们进行转换,非常人性化。
//Jdk8之前写法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8");
}
}).start();
//Jdk8写法
new Thread( () -> System.out.println("In Java8, Lambda expression") ).start();
遍历输出
输出给定数组的所有元素的简单代码
//Jdk8之前写法
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
for (Integer n : list) {
System.out.println(n);
}
// 使用 -> 的 Lambda 表达式
list.forEach(n -> System.out.println(n));
// 使用 :: 的 Lambda 表达式,一种新的表达方式
list.forEach(System.out::println);
排序
定义一个
Employee类
public class Employee {
private String name;
private int age;
private double salary;
public Employee() {
}
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public double getSalary() {
return salary;
}
@Override
public String toString() {
return "name='" + name + '\'' +
", age=" + age +
", salary=" + salary;
}
}
针对这个Employee进行排序,先按照年龄比,年龄相同按照名字比,均为升序
//初始化数据
List<Employee> employees = Arrays.asList(
new Employee("田七",27,7777.77),
new Employee("王五",24,5555.55),
new Employee("张三",23,3333.33),
new Employee("李四",24,4444.44),
new Employee("赵六",26,6666.66)
);
//排序
public void test1(){
Collections.sort(employees,(x,y) ->{
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(),y.getAge());
}
});
for (Employee emp: employees) {
System.out.println(emp);
}
}
//结果
name='张三', age=23, salary=3333.33
name='李四', age=24, salary=4444.44
name='王五', age=24, salary=5555.55
name='赵六', age=26, salary=6666.66
name='田七', age=27, salary=7777.77
补充一个知识点:
Arrays.asList()将数组转化为集合之后,它的底层其实还是数组,不可以使用修改集合的相关方法,这个数据在《阿里巴巴 Java 开发手册》中有说明,如下:
【强制】使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。 说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。 String[] str = new String[] { "a", "b" }; List list = Arrays.asList(str); 第一种情况:list.add("c"); 运行时异常。 第二种情况:str[0]= "gujin"; 那么 list.get(0)也会随之修改。
实现为真正的集合方式:
List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"))
有任何问题欢迎关注公众号【Hugh的白板】私信我,一起探讨,一起学习