如何更好的使用Java8中方法引用詳解
前言
方法引用是用來直接訪問類或者實例的已經(jīng)存在的方法或者構造方法。方法引用提供了一種引用而不執(zhí)行方法的方式,它需要由兼容的函數(shù)式接口構成的目標類型上下文。計算時,方法引用會創(chuàng)建函數(shù)式接口的一個實例。
當Lambda表達式中只是執(zhí)行一個方法調用時,不用Lambda表達式,直接通過方法引用的形式可讀性更高一些。方法引用是一種更簡潔易懂的Lambda表達式。
注意:方法引用是一個Lambda表達式,其中方法引用的操作符是雙冒號"::"。
在Java8中,使用方法引用非常簡單,如String::isEmpty,但無法使用它否定的方法引用。本文內容即如何解決此問題使得我們能夠更加全面地使用方法引用。
首先看一個使用方法引用的例子:
Stream.of("A", "", "B").filter(String::isEmpty).count()
上面代碼的輸出為1,即空字符串的數(shù)目。如果我們想要獲取非空字符串的數(shù)目,就不能直接使用方法引用了。
Stream.of("A", "", "B").filter(s -> !s.isEmpty()).count()
Java8中的Predicate,有predicate.negate()可以轉換為斷言的否定形式,但String::isEmpty卻無法這么做(String::isEmpty.negate()或者!String::isEmpty )。因為方法引用并不是一個lambda或者函數(shù)接口,它能夠被解析為一個或者多個函數(shù)接口。如,String::isEmpty至少可以被解析如下:
Predicate<String> Function<String, Boolean>
為了解決上述的問題,我們可以通過某種機制顯式地將方法引用轉換為一個函數(shù)接口:
public static <T> Predicate<T> as(Predicate<T> predicate) {
return predicate;
}
通過使用一個靜態(tài)方法,接受方法引用參數(shù),返回一個函數(shù)接口,即可實現(xiàn)方法引用到函數(shù)接口的轉換。接著,我們就可以使用方法引用來實現(xiàn)上面例子中的獲取非空字符串的數(shù)目。
Stream.of("A", "", "B").filter(as(String::isEmpty).negate()).count();
進一步還能使用各種組合的Predicate。
.filter(as(String::isEmpty).negate().and("A"::equals))
由于一個方法引用可能會被解析為多種函數(shù)接口,因此如果我們實現(xiàn)很多參數(shù)不同的as方法,那么很容易造成混淆。更好的方式則是在方法名中加入函數(shù)參數(shù)的類型來區(qū)分。
import java.util.function.*;
public class FunctionCastUtil {
public static <T, U> BiConsumer<T, U> asBiConsumer(BiConsumer<T, U> biConsumer) {
return biConsumer;
}
public static <T, U, R> BiFunction<T, U, R> asBiFunction(BiFunction<T, U, R> biFunction) {
return biFunction;
}
public static <T> BinaryOperator<T> asBinaryOperator(BinaryOperator<T> binaryOperator) {
return binaryOperator;
}
public static <T, U> BiPredicate<T, U> asBiPredicate(BiPredicate<T, U> biPredicate) {
return biPredicate;
}
public static BooleanSupplier asBooleanSupplier(BooleanSupplier booleanSupplier) {
return booleanSupplier;
}
public static <T> Consumer<T> asConsumer(Consumer<T> consumer) {
return consumer;
}
public static DoubleBinaryOperator asDoubleBinaryOperator(DoubleBinaryOperator doubleBinaryOperator) {
return doubleBinaryOperator;
}
public static DoubleConsumer asDoubleConsumer(DoubleConsumer doubleConsumer) {
return doubleConsumer;
}
public static <R> DoubleFunction<R> asDoubleFunction(DoubleFunction<R> doubleFunction) {
return doubleFunction;
}
public static DoublePredicate asDoublePredicate(DoublePredicate doublePredicate) {
return doublePredicate;
}
public static DoubleToIntFunction asDoubleToIntFunction(DoubleToIntFunction doubleToIntFunctiontem) {
return doubleToIntFunctiontem;
}
public static DoubleToLongFunction asDoubleToLongFunction(DoubleToLongFunction doubleToLongFunction) {
return doubleToLongFunction;
}
public static DoubleUnaryOperator asDoubleUnaryOperator(DoubleUnaryOperator doubleUnaryOperator) {
return doubleUnaryOperator;
}
public static <T, R> Function<T, R> asFunction(Function<T, R> function) {
return function;
}
public static IntBinaryOperator asIntBinaryOperator(IntBinaryOperator intBinaryOperator) {
return intBinaryOperator;
}
public static IntConsumer asIntConsumer(IntConsumer intConsumer) {
return intConsumer;
}
public static <R> IntFunction<R> asIntFunction(IntFunction<R> intFunction) {
return intFunction;
}
public static IntPredicate asIntPredicate(IntPredicate intPredicate) {
return intPredicate;
}
public static IntSupplier asIntSupplier(IntSupplier intSupplier) {
return intSupplier;
}
public static IntToDoubleFunction asIntToDoubleFunction(IntToDoubleFunction intToDoubleFunction) {
return intToDoubleFunction;
}
public static IntToLongFunction asIntToLongFunction(IntToLongFunction intToLongFunction) {
return intToLongFunction;
}
public static IntUnaryOperator asIntUnaryOperator(IntUnaryOperator intUnaryOperator) {
return intUnaryOperator;
}
public static LongBinaryOperator asLongBinaryOperator(LongBinaryOperator longBinaryOperator) {
return longBinaryOperator;
}
public static LongConsumer asLongConsumer(LongConsumer longConsumer) {
return longConsumer;
}
public static <R> LongFunction<R> asLongFunction(LongFunction<R> longFunction) {
return longFunction;
}
public static LongPredicate asLongPredicate(LongPredicate longPredicate) {
return longPredicate;
}
public static <T> LongSupplier asLongSupplier(LongSupplier longSupplier) {
return longSupplier;
}
public static LongToDoubleFunction asLongToDoubleFunction(LongToDoubleFunction longToDoubleFunction) {
return longToDoubleFunction;
}
public static LongToIntFunction asLongToIntFunction(LongToIntFunction longToIntFunction) {
return longToIntFunction;
}
public static LongUnaryOperator asLongUnaryOperator(LongUnaryOperator longUnaryOperator) {
return longUnaryOperator;
}
public static <T> ObjDoubleConsumer<T> asObjDoubleConsumer(ObjDoubleConsumer<T> objDoubleConsumer) {
return objDoubleConsumer;
}
public static <T> ObjIntConsumer<T> asObjIntConsumer(ObjIntConsumer<T> objIntConsumer) {
return objIntConsumer;
}
public static <T> ObjLongConsumer<T> asObjLongConsumer(ObjLongConsumer<T> objLongConsumer) {
return objLongConsumer;
}
public static <T> Predicate<T> asPredicate(Predicate<T> predicate) {
return predicate;
}
public static <T> Supplier<T> asSupplier(Supplier<T> supplier) {
return supplier;
}
public static <T, U> ToDoubleBiFunction<T, U> asToDoubleBiFunction(ToDoubleBiFunction<T, U> toDoubleBiFunction) {
return toDoubleBiFunction;
}
public static <T> ToDoubleFunction<T> asToDoubleFunction(ToDoubleFunction<T> toDoubleFunction) {
return toDoubleFunction;
}
public static <T, U> ToIntBiFunction<T, U> asToIntBiFunction(ToIntBiFunction<T, U> toIntBiFunction) {
return toIntBiFunction;
}
public static <T> ToIntFunction<T> asToIntFunction(ToIntFunction<T> ioIntFunction) {
return ioIntFunction;
}
public static <T, U> ToLongBiFunction<T, U> asToLongBiFunction(ToLongBiFunction<T, U> toLongBiFunction) {
return toLongBiFunction;
}
public static <T> ToLongFunction<T> asToLongFunction(ToLongFunction<T> toLongFunction) {
return toLongFunction;
}
public static <T> UnaryOperator<T> asUnaryOperator(UnaryOperator<T> unaryOperator) {
return unaryOperator;
}
private FunctionCastUtil() {
}
}
Stream.of("A", "", "B").filter(asPredicate(String::isEmpty).negate()).count();
英文原文:https://dzone.com/articles/put-your-java-8-method-references-to-work
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關文章
mybatis plus表的創(chuàng)建時間和修改時間的操作方法
這篇文章主要介紹了mybatis plus表的創(chuàng)建時間和修改時間的實現(xiàn)方法,本文給大家分享兩種方法,每種方法通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2021-09-09
SpringBoot對PDF進行模板內容填充與電子簽名合并詳解
這篇文章主要為大家詳細介紹了SpringBoot對PDF進行模板內容填充與電子簽名合并的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以參考下2023-12-12

