#Lambda 简介
> Java 1.8新增了Lambda表达式,让Java可以支持函数式编程(Python,Js等也支持),让代码更加的优美简洁。
—
##1.引入
在 `awt/swing` 、`Java FX`、`Android` 开发中需要大量的使用到匿名内部类,要知道这东西一写出来,代码就显得比较的臃肿,十分的不利于阅读,就如下 JavaFx 程序(简单的按钮事件)
![image](http://39.106.31.106/group1/M00/00/00/rBGejlr9jqiAaBj5AABBKDQPUeg884.png)
其实核心业务就只需要 handle方法里面中的2行
那么我们换成Lambda表达式
![image](http://39.106.31.106/group1/M00/00/00/rBGejlr9kL-Ab_cFAABW0_jasJw368.png)
为了方便理解,需要跟着如下步骤顺序阅读
##2.自定义一个lambda表达式
**1. 新建一个接口**
lambda表达式其实就是优化匿名内部类的写法如下我们定义一个Test的**接口**,要保证该接口只能有**一个抽象方法**
“` lang-java
interface Test{
public void sayHi();
}
“`
—
**2. 使用原始的匿名内部类调用**
“`lang-java
Test test = new Test(){
public void sayHi(){
System.out.println(“匿名内部类实现!”);
}
};
test.sayHi();
“`
—
**3.使用Lambda表达式**
“`lang-java
Test test = () -> {
System.out.println(“hello java8 !”);
};
test.sayHi();
“`
上面是无参的调用方式,下面我们看一下有参调用
—
**4.有返回值和有参调用**
“`lang-java
public class TestLambda{
public static void main(String[] args) {
//
Test1 test = (arg1) -> {
return “Hi ! 我叫:”+arg1;
};
System.out.println(test.sayHi(“网络巡警”));
}
}
interface Test1{
//有返回值和形参列表定义
public String sayHi(String name);
}
“`
有参和返回值都玩了 下面看一下Lambda语法
—
**5.Lambda表达式语法**
“`lang-java
//接口名 变量名 = (方法的形参) -> {
//方法体
//};
//调用方法
“`
—
**6.Lambda简写**
在日常开发中,为了体现使用Lambda的特性一般都会使用简写的方式。
这是不简写情况下
“`lang-java
Test1 test = (String arg1) -> {
return arg1;
}
“`
简写1:去掉参数类型,在Java8会**自动推断**该参数的类型,
早在JDK1.7中就加入了**类型推断**的特性比如:List<String> list = new ArrayList<>();
“`lang-java
Test1 test = (arg1) -> {
return arg1;
}
“`
简写2:形参列表为一个 时可以去掉()
“`lang-java
Test1 test = arg1 -> {
return arg1;
}
“`
简写3:单只存在一行代码时,可以去掉方法和return关键字
“`lang-java
Test1 test = arg1 -> arg1;
“`
下面可以复制如下代码测一下
“`lang-java
public class TestLambda{
public static void main(String[] args) {
//不简写
Test1 test1 = (arg1) -> {
return “Hi ! 我叫:”+arg1;
};
//形参列表只有一个,可以简写为
Test1 test2 = arg1 -> {
return “Hi ! 我叫:”+arg1;
};
//最简化状态(方法体只有一条代码,要去掉return)
//为了方便展示就没这样
//Test1 test3 = arg1 -> “Hi ! 我叫:”+arg1;
Test1 test3 = arg1 ->
“Hi ! 我叫:”+arg1;
//测试打印
test1.sayHi(“网络巡警!”);
test2.sayHi(“网络巡警!”);
test3.sayHi(“网络巡警!”);
//不简写情况
Test test4 = () -> {
System.out.println(“hello !”);
};
//简写后
Test test5 = () ->
System.out.println(“hello !”);
test4.sayHi();
test5.sayHi();
//不简写情况
Test2 test6 = (amount,quantity) -> {
return amount*quantity;
};
//简写后
Test2 test7 = (amount,quantity) ->
amount*quantity;
System.out.println(“订单价格”+test6.sayHi(200, 2));
System.out.println(“订单价格”+test7.sayHi(200, 2));
}
}
interface Test{
public void sayHi();
}
interface Test1{
//有返回值和形参列表定义
public String sayHi(String name);
}
interface Test2{
public int sayHi(int amount,int quantity);
}
“`
##3.声明函数式接口的注解
—
我们常用的一些接口Callable、Runnable、Comparator等在JDK8中都添加了@FunctionalInterface注解。
![image](http://39.106.31.106/group1/M00/00/00/rBGejlr9mwKAPvHrAACTHvB_JfY721.png)
**1、该注解只能标记在有且仅有一个抽象方法”的接口上。**
**2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。**
**3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。**
**4、该注解不是必须的,如果一个接口符合”函数式接口”定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。**
下面我在函数接口第2个抽象方法
![image](http://39.106.31.106/group1/M00/00/00/rBGejlr9m-6AYVBIAAAyLe3H6HY403.png)
毫无意外编辑器会报错
## 3.Lambda常见应用
**1 排序使用**
“`lang-java
//排序
List<String> names1 = new ArrayList<>();
names1.add(“Google “);
names1.add(“Runoob “);
names1.add(“Taobao “);
names1.add(“Baidu “);
names1.add(“Sina “);
Collections.sort(names1, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
List<String> names2 = new ArrayList<>();
names2.add(“Google “);
names2.add(“Runoob “);
names2.add(“Taobao “);
names2.add(“Baidu “);
names2.add(“Sina “);
Collections.sort(names2,(s1,s2) -> s1.compareTo(s2));
//打印
System.out.println(names1);
System.out.println(names2);
“`
—
**2 线程创建**
“`lang-java
//线程创建一
Thread thread = new Thread(() ->
System.out.println(“当前线程:”+Thread.currentThread()));
thread.start();
//线程创建二,有返回值线程
FutureTask<String> future = new FutureTask<>(() -> “123”);
new Thread(future).start();
“`