JAVA8你只需要知道這些(2)
前言
上篇文章我們講了JAVA8中介面和匿名內部類的一些新特性。這篇文章我們將繼續深入的研究JAVA8。
1.Function包
在JAVA8中引入了java.util.function包,這個包裡面全是介面,其中有四個介面值得我們注意:
1.Function 功能型介面
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
需要注意的是@FunctionalInterface註解說明這是一個函式式介面,函式式介面中只能包含一個抽象方法,如果多於一個會報錯,但是可以有預設方法,靜態方法。
從Function介面來看,該介面接收一個引數返回一個引數。
2.Consumer 消費型介面
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Consumer介面接收一個引數,但是沒有返回值。
3.Supplier 供給型介面
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
Supplier介面不接收引數,但是有返回值。
4.Predicate 斷言型介面
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
Predicate介面接收一個引數,返回一個boolean型別。
知道這4個介面有什麼用呢?這4個介面是我們接下來要講的stream的基礎,在stream中,有大量的方法用到了以上的介面。
2.Stream
Stream API真正的把函數語言程式設計風格引入了JAVA。Stream主要用來對資料進行處理,尤其是對集合資料的處理。Stream Api對應的是java.util.stream包,在這個包下面有一個Stream介面,是我們主要研究的物件。
我們先來看看建立Stream的幾種方式:
//1.使用Stream介面中的方法
Stream stream = Stream.of("1", "2", "3");
// 2. 使用Arrays.stream方法
String [] strs = new String[] {"1", "2", "3"};
stream = Arrays.stream(strs );
// 3. 使用Collection介面中的stream方法
List<String> list = Arrays.asList(strs );
stream = list.stream();
但是不論是用哪一種方式建立Stream,其內部都是通過以下程式碼實現:
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
Objects.requireNonNull(spliterator);
return new ReferencePipeline.Head<>(spliterator,
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
知道如何建立Stream以後,我們就要開始使用它:
String [] strs = new String[] {"java", "android", "ios"};
Arrays.stream(strs).filter((x)-> x.length()>3).forEach(System.out::println);
以上程式碼很簡單,首先建立了一個String陣列,然後通過Arrays.stream建立一個Stream,再通過filter方法把長度大於3的字串過濾出來,最後通過System.out::println輸出到控制檯。
到這裡就不得不提到Stream的操作了:
Stream操作分為中間操作和終端操作,中間操作就比如上面的filter方法,終端操作就比如上面的forEach方法。Stream的中間操作會惰性執行,只有執行到終端操作了才會立即去處理。這樣的好處就是可以提升效能。
中間操作又分為有狀態和無狀態兩種,有狀態的操作必須等到所有元素處理完之後才知道最終結果,比如排序操作,在讀取完所有元素前,就不能確定排序的結果。而無狀態的操作中,元素的處理不受前面元素的影響,比如filter操作就是無狀態的,當前元素的操作不會受到前面元素的影響。
終端操作也分為非短路操作和短路操作,短路操作即不用處理全部元素就可以返回結果,比如anyMatch方法,找到第一個滿足條件的元素就返回。非短路操作就是要處理完全部元素才可以返回結果。
中間操作包括:map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
終端操作包括:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
3.方法引用
可能細心的朋友已經發現了,在以上我們的程式碼中使用了System.out::println而不是System.out.prinlnt。這種語法我們以前似乎沒有見過?對,它叫方法引用,這也是JAVA8中的新特性,我們來看看它的語法:
1.引用靜態方法: 類名稱::靜態方法名
2.引用普通方法: 例項化物件名::普通方法名
3.引用特定類方法: 特定類::普通方法名
4.引用構造方法: 類名稱::new
你可能會說,不就是把以前的方法呼叫由.變成了::麼?有什麼可稀奇的?方法引用跟以前方法呼叫最大的區別在於,你可以用另外一個方法來引用該方法,說通俗一點就是可以給方法取一個別名,例如:
範例:把Int型轉換為String
@FunctionalInterface
interface Action<P,R>{
R convert(P p);
}
public static void main(String[]args){
Action<Integer,String> a=String::valueOf;
String str=a.convert(123);
System.out.println(str);
}
在上面程式碼中,我們首先定義了函式式介面,關於函式式介面的定義我們上篇文章已經說過了,要是忘記了可以再回上篇文章看看。Action介面中有convert方法,接收一個引數,返回一個值。這跟我們String類中的valueOf方法一樣,valueOf方法也是傳入一個引數,返回一個值:
public static String valueOf(int i)
所以我們就可以用convert來引用valueOf方法,可以看見我們的convert方法是沒有被實現的,他的功能完全取決於valueOf方法。並且因為valueOf方法是靜態的,所以我們按照方法引用的語法,可以用類名::靜態方法名直接引用。
範例:把小寫字串轉換為大寫
@FunctionalInterface
interface Action<R>{
R convert();
}
public static void main(String[]args){
Action<String> a="abc"::toUpperCase;
String str=a.convert();
System.out.println(str);
}
在上面程式碼中,我們通過方法引用把小寫的abc,轉換為大寫的ABC,在使用方法引用的時候,我們用了"abc"這就是String類的一個例項,而toUpperCase的定義是一個普通方法:
public String toUpperCase()
範例:比較兩個字元的大小
@FunctionalInterface
interface Action<P>{
int convert(P p1,P p2);
}
public static void main(String[]args){
Action<String> a=String::compareTo;
System.out.println(a.convert("a","b"));
}
在以上程式碼中我們引用了compareTo方法來比較兩個字串的大小。但是我們來看該方法的定義:
public int compareTo(String anotherString)
它竟然不是靜態方法,我們卻用類名直接引用,這是為什麼?正常情況下,類名::方法名,這個方法肯定是靜態方法。但是為什麼這裡普通方法也可以呢?這就要分析一下compareTo這個方法了,這個方法是兩個字串進行對比,正常情況下的寫法應該是"a".compareTo("b"),對應的方法引用應該是"a"::compareTo。
如果是這樣,我們定義函式式介面的時候,就應該定義成以下這樣:
@FunctionalInterface
interface Action<P>{
int convert(P p1);
}
public static void main(String[]args){
Action<String> a="a"::compareTo;
System.out.println(a.convert("b"));
}
如果介面定義成這樣,就可以使用"a"::compareTo這種形式的方法引用。到這裡聰明的你應該明白,為什麼在上面可以通過類名引用普通方法了吧?我們想想在String類裡面除了compareTo還有其他方法沒?很多是不是?equals,endsWith都屬於,所以他們都可以通過把方法引數定義為兩個,然後用類名::方法名。
class ShopCar{
private String name;
private double price;
private int amount;
public ShopCar(String name,double price,int amount){
this.name=name;
this.price=price;
this.amount=amount;
}
public int getAmount() {
return amount;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "商品名:"+this.name+" 價格:"+this.price+" 數量:"+this.amount;
}
}
@FunctionalInterface
interface Action<C>{
C create(String name,double price,int amount);
}
public static void main(String[]args){
Action<ShopCar> a=ShopCar :: new;
ShopCar car=a.create("蘋果",5,2);
System.out.println(car);
}
以上程式碼演示瞭如何通過類名稱::new 來構造一個ShopCar物件。
結語:
今天的文章主要講了JAVA8新引入的兩個包和方法引用,其中Function包是基礎,大家一定要多多理解。Stream包是函數語言程式設計風格的主要提現,下一篇文章我們會著重介紹Stream介面中的方法。
如果你覺得本篇文章幫助到了你,希望大爺能夠打賞。
本文為原創文章,轉載請註明出處!
相關文章
- 關於Android Gradle你需要知道這些(2)AndroidGradle
- 這些CSS提效技巧,你需要知道!CSS
- 關於MySQL引數,這些你要知道MySql
- 入門Python,這些優點你要知道!Python
- Java8的這些集合騷操作,你掌握了嘛?Java
- Java8新特性,你應該瞭解這些!Java
- 關於神經網路:你需要知道這些神經網路
- Netty中的這些知識點,你需要知道!Netty
- 關於專案採購管理,這些你需要知道
- 採購CRM系統,你需要知道這些費用
- 關於Android Gradle你需要知道這些(4)AndroidGradle
- 關於Android Gradle你需要知道這些(3)AndroidGradle
- 關於Android Gradle你需要知道這些(1)AndroidGradle
- 讓孩子愛上讀書,你需要知道這些方法
- CSS你可以不寫,但這些規範必須要知道!CSS
- 關於 TDengine 3.0 資料訂閱,你需要知道這些
- 建立合格的跨職能團隊,你需要知道這些!
- 這些Java8官方挖過的坑,你踩過幾個?Java
- 【Java8新特性】關於Java8中的日期時間API,你需要掌握這些!!JavaAPI
- 作為程式設計師,這些實用工具你必須要知道!程式設計師
- 想要App做得美,這些UI/UX設計趨勢你要知道啊APPUIUX
- “作弊”:只需要知道這一個 Linux 命令就夠了Linux
- 【格物獵蹤】關於OpenVPN反射攻擊,你還需要知道這些!反射
- 你需要知道這些關於技術美術的知識構成
- AICC 2021,這些AI熱門話題你一定要知道AI
- [譯] 關於Angular的變更檢測(Change Detection)你需要知道這些Angular
- 為什麼要使用Linux作業系統?這些你有必要知道!Linux作業系統
- 學習 React 前你需要知道些什麼React
- 考不考CCSP認證,這些知識也要知道
- 文章違規資訊檢測軟體有哪些?這些容易違規的資訊你要知道
- 企業建站為什麼要選擇雲伺服器?這些常識你要知道!伺服器
- linux嵌入式程式設計開發必備知識,這些你都要知道Linux程式設計
- 每日話題:明天開始執行網路支付實名制你需要知道這些
- 關於 Git 你需要知道的一些事情Git
- 關於Flutter你要知道的可能都在這兒Flutter
- 微服務開發,這10個點你要知道微服務
- 要知道AI的工作原理,Get這些點就夠了AI
- 對於Redis中設定了過期時間的Key,你需要知道這些內容Redis