Java8 由Oracle在2014年發佈,是繼Java5之後最具革命性的版本。
Java8吸收其他語言的精髓帶來了函數式編程,lambda表達式,Stream流等一系列新特性,學會了這些新特性,可以讓你實現高效編碼優雅編碼。
熱門精選文章,更多技術乾貨,微信搜索訂閱號【碼者圈】:
【Java8新特性】04 詳解Lambda表達式中Predicate Function Consumer Supplier函數式接口
【Java8新特性】03 Stream流式數據處理
【Java8新特性】02 函數式接口和Lambda表達式實戰練習:環繞執行模式使行爲參數化
【Java8新特性】01 函數式接口和Lambda表達式你真的會了嗎
函數式接口
函數式接口是指只定義了一個抽象方法的接口,不包括default默認方法。
函數式接口的抽象方法的簽名稱爲函數描述符,通過函數描述符可以很好得到Lambda表達式的簽名。
常見的函數式接口有:Runnable, Callable, Comparator等。除此之外,Java8設計者還新增了一些比較抽象的函數式接口,比如:Predicate, Consumer, Supplier, Function, UnaryOperator, BinaryOperator等, 這些函數式接口定義在java.util.function包中。
接下來詳細介紹function包中定義的抽象接口:
1. Predicate
(1)定義
Predicate是謂詞的意思,用來判斷泛型T對象是否符合條件,如果符合返回true,否則返回false。
查看jdk源碼,定義了一個抽象方法test:
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
(2)使用方法
Predicate是一個接口所以不能直接實例化,可以使用匿名類或者Lambda表達式實例化。以Lambda爲例:
// 接收string對象,判斷是否爲空,返回boolean
Predicate predicate = (String str) -> str.isEmpty();
下面以一個校驗參數的實例說明:
@Test
public void testPredicate() {
String input = "hello java8";
if (validate(input, (str) -> !str.isEmpty() && str.length() > 5)) {
// 校驗輸入
System.out.println("valid input");
}
}
// 第二個參數接收一個Predicate實例
private <T> boolean validate(T input, Predicate<T> predicate) {
return predicate.test(input);
}
(3)函數描述符
Predicate: T -> boolean
接受泛型T對象返回boolean。
注意:java.util.function包中還針對基本類型封裝了類似IntPredicate, LongPredicate等接口,這無非是表明只接受Int或Long類型的輸入,後面Consumer等函數式接口與這個類似,本文不再贅述。
2. Consumer
(1)定義
Consumer是消費者的意思,用來接收一個泛型T對象,執行相關操作,最後返回void。
查看jdk源碼,定義了一個抽象方法accept:
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
(2)使用方法
使用Lambda表達式實例化Consumer接口:
Consumer<String> consumer = (str) -> System.out.println(str);
下面以打印字符串的實例講解Consumer的用法:
@Test
public void testConsumer() {
String input = "hello java8";
// 打印輸入
consume(input, (str) -> System.out.println(str));
}
private <T> void consume(T input, Consumer<T> consumer) {
consumer.accept(input);
}
(3)函數描述符
Consumer: T -> void
接受泛型T對象返回void。
3. Supplier
(1)定義
Supplier是提供者的意思,用來生成泛型T對象。
查看jdk源碼,定義了一個抽象方法get:
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
(2)使用方法
使用Lambda表達式實例化Supplier接口:
Supplier supplier = () -> "Hello Java8 supplier";
下面以獲取當前時間的實例講解Supplier的用法:
@Test
public void testSupplier() {
// 獲取當前時間
Long currentTime = supply(() -> System.currentTimeMillis());
}
private <T> T supply(Supplier<T> supplier) {
return supplier.get();
}
(3)函數描述符
Supplier: void -> T
接受void返回泛型T對象。
4. Function
(1)定義
Function是函數的意思,用來定義一個抽象函數,接收泛型T對象,返回泛型R對象。
查看jdk源碼,定義了一個抽象方法apply:
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
(2)使用方法
使用Lambda表達式實例化Function接口:
Function<String, Integer> function = (str) -> str.length();
下面以判斷輸入是否以指定字符串開頭的實例講解Function的用法:
@Test
public void testFunction() {
String input = "hello java8";
if(func(input, (String str) -> str.startsWith("hello"))) {
System.out.println("start with hello");
}
}
private <T, R> R func(T t, Function<T, R> function) {
return function.apply(t);
}
(3)函數描述符
Function: T -> R
接受泛型T對象,返回泛型R對象。
5. UnaryOperator
(1)定義
UnaryOperator是一元操作符的意思,接收一個泛型T對象參數,返回相同T類型對象。
查看jdk源碼,UnaryOperator繼承自Function接口,定義了一個identity方法:
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
*
* @param <T> the type of the input and output of the operator
* @return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
(2)使用方法
使用Lambda表達式實例化UnaryOperator接口:
UnaryOperator<Integer> unaryOperator = (Integer i) -> i * i;
下面以整數遞增的實例講解UnaryOperator的用法:
@Test
public void testUnaryOperator() {
UnaryOperator<Integer> unaryOperator = (Integer i) -> i * i;
int input = 0;
int result = unaryOperate(input, (Integer i) -> i + 1);
// output: 1
System.out.println(result);
}
private <T> T unaryOperate(T t, UnaryOperator<T> unaryOperator) {
return unaryOperator.apply(t);
}
(3)函數描述符
UnaryOperator: T -> T
接受泛型T對象,返回泛型T對象。
6. BinaryOperator
(1)定義
BinaryOperator是二元操作符的意思,接收兩個相同泛型參數類型T,返回R類型對象。
查看jdk源碼,BinaryOperator繼承自BiFunction接口,繼承了BiFunction的apply方法:
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
/**
* Applies this function to the given arguments.
*
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
R apply(T t, U u);
}
(2)使用方法
使用Lambda表達式實例化BinaryOperator接口:
BinaryOperator<String> binaryOperator = (String str1, String str2) -> str1 + str2;
下面以整數求和實例講解BinaryOperator的用法:
@Test
public void testBinaryOperator() {
int a1 = 10;
int a2 = 20;
int sum = binaryOperate(a1, a2, (Integer i1, Integer i2) -> i1 + i2);
// output: 30
System.out.println(sum);
}
private <T> T binaryOperate(T t1, T t2, BinaryOperator<T> binaryOperator) {
return binaryOperator.apply(t1, t2);
}
(3)函數描述符
BinaryOperator: (T, T) -> T
接受兩個泛型T對象,返回一個泛型T對象。
7. 總結
java.util.function包中定義了很多函數式抽象接口,只要記住它們的函數描述符就可以很方便的知道他們的使用方法。
- Predicate: T -> boolean
- Consumer: T -> void
- Supplier: void -> T
- Function: T -> R
- UnaryOperator: T -> T
- BinaryOperator: (T, T) -> T
【碼者圈】屬於編碼者自己的圈子,微信掃描二維碼關注,第一時間獲取更多技術乾貨!