Java 8 中的方法引用,怎么用到最好?
在Java8中,使用方法引用非常簡單,如String::isEmpty,但無法使用它否定的方法引用。本文內(nèi)容即如何解決此問題使得我們能夠更加全面地使用方法引用。
首先看一個使用方法引用的例子:
Stream.of("A", "", "B").filter(String::isEmpty).count()上面代碼的輸出為1,即空字符串的數(shù)目。
如果我們想要獲取非空字符串的數(shù)目,就不能直接使用方法引用了。
Stream.of("A", "", "B").filter(s -> !s.isEmpty()).count()
Java8中的Predicate,有predicate.negate()可以轉(zhuǎn)換為斷言的否定形式,但String::isEmpty卻無法這么做(String::isEmpty.negate()或者!String::isEmpty)。
因為方法引用并不是一個lambda或者函數(shù)接口,它能夠被解析為一個或者多個函數(shù)接口。如,String::isEmpty至少可以被解析如下:
Predicate<String>
Function
為了解決上述的問題,我們可以通過某種機(jī)制顯式地將方法引用轉(zhuǎn)換為一個函數(shù)接口:
public static <T> Predicate<T> as(Predicate<T> predicate) {return predicate;}
通過使用一個靜態(tài)方法,接受方法引用參數(shù),返回一個函數(shù)接口,
即可實現(xiàn)方法引用到函數(shù)接口的轉(zhuǎn)換。
接著,我們就可以使用方法引用來實現(xiàn)上面例子中的獲取非空字符串的數(shù)目。
Stream.of("A", "", "B").filter(as(String::isEmpty).negate()).count();
進(jìn)一步還能使用各種組合的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
譯文:https://www.rowkey.me/blog/2017/09/02/java8-method-reference-work/
推薦閱讀:
