JDK8的新特性:
Lambda表達式與Functional接口
在JDK8之前,Java是不支援函數式程式設計的,所謂的函數程式設計,即可了解是将一個函數(也稱為“行為”)作為一個參數進行傳遞。通常我們提及得更多的是面向對象程式設計,面向對象程式設計是對資料的抽象(各種各樣的POJO類),而函數式程式設計則是對行為的抽象(将行為作為一個參數進行傳遞)。在JavaScript中這是很常見的一個文法特性,但在Java中将一個函數作為參數傳遞這卻行不通,好在JDK8的出現打破了Java的這一限制
Lambda表達式由3部分組成:
參數 -> 函數體
能夠接收Lambda表達式的參數類型,是一個隻包含一個方法的接口。隻包含一個方法的接口稱之為“函數接口
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
/**
* 隻有一個抽象方法的接口是函數式接口。
* @author 27783
*
*/
public interface Lambad {
public void add();
}
View Code
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class LambadDemo {
public static void test(Lambad lambad){
lambad.add();
}
//現在我要執行add方法但是我沒有實作類
//我們知道可以使用匿名内部類
public static void main(String[] args) {
//匿名内部類的寫法
test(new Lambad() {
@Override
public void add() {
System.out.println(10+5);
}
});
//使用lambad表達式
test(() -> {System.out.println(10+5);});
}
}
View Code
可以看到,隻要是一個接口中隻包含一個方法,則可以使用Lambda表達式,這樣的接口稱之為“函數接口”。
上面的函數接口比較簡單不包含參數,也不包含傳回值
有參無傳回值的:
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
/**
* 隻有一個抽象方法的接口是函數式接口。
* @author 27783
*
*/
public interface Lambad {
public void add(int a,int b);
}
View Code
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class LambadDemo {
public static void test(Lambad lambad){
int a=10;int b=20;
lambad.add(a,b);
}
//現在我要執行add方法但是我沒有實作類
//我們知道可以使用匿名内部類
public static void main(String[] args) {
//匿名内部類
test(new Lambad() {
@Override
public void add(int a, int b) {
System.out.println(a+b);
}
});
//使用lambad表達式
test((a,b) ->{System.out.println(a+b);});
}
}
View Code
有參有傳回值:
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
/**
* 隻有一個抽象方法的接口是函數式接口。
* @author 27783
*
*/
public interface Lambad {
public int add(int a,int b);
}
View Code
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class LambadDemo {
public static int test(Lambad lambad){
int a=10;int b=20;
int c=lambad.add(a,b);
return c;
}
//現在我要執行add方法但是我沒有實作類
//我們知道可以使用匿名内部類
public static void main(String[] args) {
//匿名内部類
test(new Lambad() {
@Override
public int add(int a, int b) {
return a+b;
}
});
//使用lambad表達式
int c=test((a,b) -> {return a+b;} );
System.out.println(c);
}
}
View Code
使用泛型:
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
/**
* 隻有一個抽象方法的接口是函數式接口。
* @author 27783
*
*/
public interface Lambad<T> {
public int add(T a,T b);
}
View Code
package com.xk;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class LambadDemo {
public static int test(Lambad<Integer> lambad){
int a=10;int b=20;
int c=lambad.add(a,b);
return c;
}
//現在我要執行add方法但是我沒有實作類
//我們知道可以使用匿名内部類
public static void main(String[] args) {
// //匿名内部類
// test(new Lambad<Integer>() {
//
// @Override
// public int add(Integer a, Integer b) {
// // TODO Auto-generated method stub
// return a+b;
// }
// });
//使用lambad表達式
int c=test((Integer a, Integer b) -> {return a+b;} );
System.out.println(c);
}
}
View Code
使用泛型後,在我們使用的時候,注意要設定參數的類型,不設定的化,系統會自動根據上下文來推導這個資料類型,但是最好還是寫上。
這三種基本情況已經大緻清楚了,特别是需要弄清,什麼時候可以使用Lambda表達式代替匿名内部類,也就是Lambda表達式的應用場景是函數接口。Lambda表達式這一新特性在JDK8中的引入,更大的好處則是集合API的更新,新增的Stream類庫,使得我們在周遊使用集合時不再像以往那樣不斷地使用for循環
stream:
在jdk8中引入了新的概念:
流是Java8引入的全新概念,它用來處理集合中的資料,我們可以把他了解為一種進階集合。
我們知道集合的一些操作很麻煩,需要寫大量的代碼 而流是以聲明的形式操作集合,它就像SQL語句,我們隻需告訴流需要對集合進行什麼操作,它就會自動進行操作,并将執行結果交給你,無需我們自己手寫代碼。
是以,流的集合操作對我們來說是透明的,我們隻需向流下達指令,它就會自動把我們想要的結果給我們。由于操作過程完全由Java處理,是以它可以根據目前硬體環境選擇最優的方法處理,我們也無需編寫複雜又容易出錯的多線程代碼了。
流的特點:
隻能周遊一次。流在使用一次後就會關閉了,我們無法進行下一次操作了。當然我們可以重新去開始一個流,進行操作。
采用内部疊代方式。若要對集合進行處理,則需我們手寫處理代碼,這就叫做外部疊代。而要對流進行處理,我們隻需告訴流我們需要什麼結果,處理過程由流自行完成,這就稱為内部疊代。
流的操作分為兩種,分别為中間操作 和 終端操作。
-
-
中間操作
當資料源中的資料上了流水線後,這個過程對資料進行的所有操作都稱為“中間操作”。
中間操作仍然會傳回一個流對象,是以多個中間操作可以串連起來形成一個流水線。
-
終端操作
當所有的中間操作完成後,若要将資料從流水線上拿下來,則需要執行終端操作。
終端操作将傳回一個執行結果,這就是你想要的資料。
-
流的操作過程
使用流一共需要三步:
- 準備一個資料源
-
執行中間操作
中間操作可以有多個,它們可以串連起來形成流水線。
-
執行終端操作
執行終端操作後本次流結束,你将獲得一個執行結果。
流的使用:
在使用流之前,首先需要擁有一個資料源,并通過StreamAPI提供的一些方法擷取該資料源的流對象。資料源可以有多種形式:集合、數組、多個值、檔案。
package com.xk;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class StreamDemo {
//Stream的一些操作
public static void main(String[] args) {
//集合擷取流
List<Integer> list = new ArrayList<Integer>();
Stream<Integer> stem=list.stream();
//數組擷取流
String[] name={"悟空","八戒","悟淨"};
Stream<String> result=Arrays.stream(name);
//值擷取流
Stream<String> ste = Stream.of("悟空","八戒","悟淨");
//檔案操作擷取流
try {
Stream stream=Files.lines(Paths.get("路徑名"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
View Code
流的操作:這裡我們主要使用集合操作。
package com.xk;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class StreamTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
// 篩選操作:filter
List<Integer> result = list.stream().filter(temp -> temp < 10).collect(Collectors.toList());
// 去重
List<Integer> result = list.stream().distinct().collect(Collectors.toList());
// 截取:截取多少個元素:最大不能超過 list.size();
List<Integer> result = list.stream().limit(5).collect(Collectors.toList());
// 跳過多少個元素
List<Integer> result = list.stream().skip(4).collect(Collectors.toList());
}
}
View Code
package com.xk;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
*作者:吳志龍
*日期:2018年8月17日
*/
public class StreamTest {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student student1 = new Student("八戒", 500);
Student student = new Student("悟空", 500);
Student student2 = new Student("悟靜", 500);
list.add(student1);
list.add(student);
list.add(student2);
// 對流中的每個元素執行一個函數,
// 使得元素轉換成另一種類型輸出。
// 流會将每一個元素輸送給map函數,
// 并執行map中的Lambda表達式,
// 最後将執行結果存入一個新的流中
List<String> result = list.stream().map(Student::getName).collect(Collectors.toList());
result.forEach(temp -> {
System.out.println(temp);
});
// 是否比對任一進制素
// anyMatch用于判斷流中是否存在至少一個元素滿足指定的條件,
// 這個判斷條件通過Lambda表達式傳遞給anyMatch,執行結果為boolean類型
boolean flag = list.stream().anyMatch((temp) -> temp.getName().equals("悟空"));
System.out.println(flag);
// findAny能夠從流中随便選一個元素出來,它傳回一個Optional類型的元素。
Optional<Student> option = list.stream().findAny();
}
}
View Code
Optional介紹
Optional是Java8新加入的一個容器,這個容器隻存1個或0個元素,它用于防止出現NullpointException,它提供如下方法:
-
isPresent()
判斷容器中是否有值。
-
ifPresent(Consume lambda)
容器若不為空則執行括号中的Lambda表達式。
-
T get()
擷取容器中的元素,若容器為空則抛出NoSuchElement異常。
-
T orElse(T other)
擷取容器中的元素,若容器為空則傳回括号中的預設值
轉載于:https://www.cnblogs.com/wuzhilong/p/9434930.html