1. Lambda基础
lambda表达式允许你通过表达式来代替功能接口。Lambda表达式的本质只是一个"语法糖"。
1.1. Lambda组成
由三个部分组成
- 第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数。
- 第二部分为一个箭头符号:->。
- 第三部分为方法体,可以是表达式和代码块。
parameters) -> expression
(int a,int b) -> return a + b; //求和
(parameters) -> { statements; }
(int a) -> {System.out.println("a = " + a);} //打印,无返回值
(int a) -> {return a * a;} //求平方
1.2. 函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。划重点:函数式接口可以被隐式转换为 lambda 表达式。
函数式接口的定义,如:
//@FunctionalInterface是可选的,但加上该标注编译器会帮你检查接口是否符合函数接口规范。就像加入@Override标注会检查是否重载了函数一样
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}
那么就可以使用Lambda表达式来表示该接口的一个实现:
GreetingService greetService1 = message -> System.out.println("Hello " + message);
确定了某个interface是用于Lambda表达式,请一定要加上@FunctionalInterface,防止他人增加另外一个抽像方法。
1.3. 双冒号操作符
双冒号运算方法引用,格式:类名::方法名。一般是用作Lambda表达式。
表达式person -> person.getName(); 替换成:Person::getName
表达式() -> new HashMap<>();替换成:HashMap::new
2.Lambda应用
2.1.Lambda和匿名内部类
Lambda表达式可以简化匿名内部类的书写,但Lambda表达式并不能取代所有的匿名内部类,只能用来取代函数式接口(Functional Interface)的简写(接口名和函数名都简写掉了)。例如:
// JDK7 匿名内部类写法
new Thread(new Runnable(){// 接口名
@Override
public void run(){// 方法名
System.out.println("Thread run()");
}
}).start();
// JDK8 Lambda表达式写法
new Thread(
() -> System.out.println("Thread run()")// 省略接口名和方法名
).start();
//简写new Runnable(){}
Runnable run = () -> System.out.println("Hello World");// 1
需要注意:在匿名内部类中this指的是自身的引用,在Lambda表达式中this指的是外部。
2.2. 用内部迭代取代外部迭代
有时候代码里嵌套2个以上的for循环的都比较难读懂,使用内部迭代进行简化。
String[] atp = {"Rafael Nadal", "Novak Djokovic",
"Stanislas Wawrinka",
"David Ferrer","Roger Federer",
"Andy Murray","Tomas Berdych",
"Juan Martin Del Potro"};
List<String> players = Arrays.asList(atp);
// 以前的循环方式
for (String player : players) {
System.out.print(player + "; ");
}
// 使用 lambda 表达式以及函数操作(functional operation)
players.forEach((player) -> System.out.print(player + "; "));
// 在 Java 8 中使用双冒号操作符(double colon operator)
players.forEach(System.out::println);
3. 知识拓展
(1)匿名内部类
以往先建抽象类,继承这个抽象类再开始创建对象的,否则对象是无法创建的,为了简便使用匿名内部类,允许在主方法当中进行抽象类的实例化,同时也可以进行对象的创建。
//抽象类
abstract class Chouxiang
{
String name="Geek Song";//抽象类的属性是不会被调用的,除了方法
public void say3()
{
System.out.println("这是抽象类当中的方法,抽象类当中是允许有具体方法来进行实现的,接口不行");
}
}
public class innerclass {
public static void main(String[] args) {
//匿名内部类
Chouxiang c=new Chouxiang() {
String name="Geek Song too";
public void say3()
{
System.out.println("这是匿名内部类当中的方法,重写了抽象类的方法");
System.out.println(name);
}
}}
网友评论