Lambda是什麼
Lambda 表達式,也可稱爲閉包,它是推動 Java 8 發佈的最重要新特性,Lambda 允許把函數作爲一個方法的參數(函數作爲參數傳遞進方法中),使用 Lambda 表達式可以使代碼變的更加簡潔緊湊。
Lambda是一個匿名函數
()->{}
():描述參數列表;{}:用來描述方法體
->:lambda運算符,稱作 goes to
函數式接口
說到Lambda就不得不說函數式接口
什麼是函數式接口?
- 只包含一個抽象方法的接口,稱爲函數式接口。
- 可以通過Lambda表達式來創建該接口的對象(若Lambda表達式拋出一個受檢異常,那麼該異常需要在目標接口的抽象方法上進行聲明)
- 在Java8後可以在任意函數式接口上使用@FunctionalInterface註解,其主要用於編譯級錯誤檢查,加上該註解,當你寫的接口不符合函數式接口定義的時候,編譯器會報錯。
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
}
Lambda的使用條件
從以上能夠看出,Lambda的使用條件是接口中有且只有一個必須實現的方法,如果有一個以上,Lambda就不知道該實現那個方法,在java8中新增了接口的默認方法,Lambda不受其影響
默認方法:
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
default void test(){
System.out.println("默認方法");
}
}
Lambda的使用
先創建六個接口來分別測試
@FunctionalInterface
public interface LambdaNoneReturnMutipleParm {
void test(int a,int b);
default void test(){
System.out.println("默認方法");
}
}
-----
@FunctionalInterface
public interface LambdaNoneReturnNoneParm {
void test();
}
-----
@FunctionalInterface
public interface LambdaNoneReturnSingleParm {
void test(int a);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnMutipleParm {
int test(int a,int b);
}
-----
@FunctionalInterface
public interface LambdaSingleReturnNoneParm {
int test();
}
-----
@FunctionalInterface
public interface LambdaSingleReturnSingleParm {
int test(int a);
}
Lambda表達式的基礎語法
//1.Lambda表達式的基礎語法
//無參無返回
LambdaNoneReturnNoneParm lambda1 = ()->{
System.out.println("LambdaNoneReturnNoneParm");
};
lambda1.test();
//單個參數,無返回
LambdaNoneReturnSingleParm lambda2 = (int a)->{
System.out.println("LambdaNoneReturnSingleParm: "+a);
};
lambda2.test(77);
//多個參數,無返回
LambdaNoneReturnMutipleParm lambda3 = (int a,int b)->{
System.out.println("LambdaNoneReturnMutipleParm: a:"+a+",b: "+b+",a+b: "+(a+b));
};
lambda3.test(10,77 );
//無參,有返回
LambdaSingleReturnNoneParm lambda4 = ()->{
return 77;
};
int ret = lambda4.test();
System.out.println(ret);
//單個參數,有返回
LambdaSingleReturnSingleParm lambda5 = (int a)->{
return a*10;
};
int ret2 = lambda5.test(7);
System.out.println(ret2);
//多個參數,有返回
LambdaSingleReturnMutipleParm lambda6 = (int a,int b)->{
return a*b;
};
int ret3 = lambda6.test(7,11);
System.out.println(ret3);
Lambda語法精簡
- 參數類型,由於已經在接口的抽象方法中,已經定義了參數的數量和類型,所以在表達式中,參數的類型可以省略(參數類型要麼都省略,要麼都不省略,不能只省略其中一個)
//多個參數,無返回
LambdaNoneReturnMutipleParm lambda = (a,b)->{
System.out.println("LambdaNoneReturnMutipleParm: a:"+a+",b: "+b+",a+b: "+(a+b));
};
lambda.test(10,77 );
- 參數小括號,如果參數的數量只要一個,小括號可以省略
//單個參數,無返回
LambdaNoneReturnSingleParm lambda2 = a->{
System.out.println("LambdaNoneReturnSingleParm: "+a);
};
lambda2.test(77);
- 方法大括號,如果方法體中只有一條語句,大括號可以省略
//無參無返回
LambdaNoneReturnNoneParm lambda3 = ()-> System.out.println("LambdaNoneReturnNoneParm");
lambda3.test();
- 如果方法體中,唯一的一條語句是返回語句,在省略大括號的同時必須省略掉return
LambdaSingleReturnNoneParm lambda4 = ()-> 77;
int ret = lambda4.test();
System.out.println(ret);
lambda語法進階
- 方法引用:可以快速的將一個lambda表達式的實現指向一個已經實現的方法
語法;方法的屬於者::方法名
參數類型和數量要和接口中的方法一致,返回值也一樣
靜態方法引用:
public class syntax3 {
public static void main(String[] args) {
//lambda語法進階
//方法引用:可以快速的將一個lambda表達式的實現指向一個已經實現的方法
//語法,方法的屬於者::方法名
//參數類型和數量要和接口中的方法一致,返回值也一樣
// LambdaSingleReturnSingleParm lambda1 = a -> a*2;
// LambdaSingleReturnSingleParm lambda2 = a -> a*2;
LambdaSingleReturnSingleParm lambda1 = a -> change(a);
int ret = lambda1.test(2);
System.out.println("ret: "+ret);
//方法引用
LambdaSingleReturnSingleParm lambda2 = syntax3::change;
int ret2 = lambda2.test(2);
System.out.println("ret2: "+ret2);
}
private static int change(int a){
return a*2;
}
}
構造方法的引用:
先定義一個Person類
public class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person() {
System.out.println("無參構造器");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有參構造器: "+name+",age: "+age);
}
}
PersonCreater creater = ()->new Person();//一般的Lambda用法
Person a = creater.getPerson();
//無參構造方法的引用
PersonCreater creater1 = Person::new;//構造方法引用
Person b =creater1.getPerson();
//多個參數構造方法引用
PersonCreaterWithParm creater2 = Person::new;
Person c = creater2.getPerson("林北",21 );
-----
@FunctionalInterface
interface PersonCreater{
Person getPerson();
}
@FunctionalInterface
interface PersonCreaterWithParm{
Person getPerson(String name,int age);
}
Java四大核心函數式接口
在使用Lambda表達式的時候總要自己寫函數式接口嗎? 當然不是這樣了,Java8裏面提供了四大核心的函數式供我們使用
函數式接口 | 參數類型 | 返回類型 | 作用 |
---|---|---|---|
Consumer | T | void | 對類型T參數操作,無返回結果,包含方法 void accept(T t) |
Supplier | 無 | T | 返回T類型參數,方法時 T get() |
Function | T | R | 對類型T參數操作,返回R類型參數,包含方法 R apply(T t) |
Predicate | T | Boolean | 斷言型接口,對類型T進行條件篩選操作,返回boolean,包含方法 boolean test(T t) |
使用
/**
* Consumer<T>
*/
@Test
public void ConsumerTest(){
consumer("Consumer",(m)-> System.out.println("我是ConsumerTest接口:"+m) );
}
public void consumer(String name, Consumer consumer){
consumer.accept(name);
}
/**
* Supplier<T>
*/
@Test
public void SupplierTest() {
List<Integer> list = getNumList(7,()->(int)Math.random()*8);
list.forEach(System.out::println);
}
public List<Integer> getNumList(int n, Supplier<Integer> supplier){
List<Integer> list = new ArrayList<>();
for(int i = 0;i<n;i++){
Integer num = supplier.get();
list.add(num);
}
return list;
}
/**
* Function<T,R>
*/
@Test
public void FunctionTest(){
String str=strHandle("Hello World",(string)->string.substring(2,5 ));
System.out.println(str);
}
public String strHandle(String str, Function<String,String> fun){
return fun.apply(str);
}
/**
* Predicate<T>
*/
@Test
public void PredicateTest(){
List<String> list1= Arrays.asList("Predicate","Function","Supplier","Consumer");
List<String> list=filterList(list1,(s)->s.length()>8);
for (String s : list) {
System.out.println(s);
}
}
public List<String> filterList(List<String> list, Predicate<String> predicate){
List<String> strings=new ArrayList<>();
for (String string : list) {
if(predicate.test(string)){
strings.add(string);
}
}
return strings;
}