Java 8 中的方法引用,怎么用到最好?

Java技术栈

www.javastack.cn

打开网站看更多优质文章

Java8中,使用方法引用非常简单,如String::isEmpty,但无法使用它否定的方法引用。本文内容即如何解决此问题使得我们能够更加全面地使用方法引用。

首先看一个使用方法引用的例子:

Stream.of("A", "", "B").filter(String::isEmpty).count()

上面代码的输出为1,即空字符串的数目。如果我们想要获取非空字符串的数目,就不能直接使用方法引用了。

Stream.of("A", "", "B").filter(s -> !s.isEmpty()).count()

Java8中的Predicate,有predicate.negate()可以转换为断言的否定形式,但String::isEmpty却无法这么做(String::isEmpty.negate()或者!String::isEmpty)。

因为方法引用并不是一个lambda或者函数接口,它能够被解析为一个或者多个函数接口。如,String::isEmpty至少可以被解析如下:

  • Predicate

  • Function

为了解决上述的问题,我们可以通过某种机制显式地将方法引用转换为一个函数接口:

public static  Predicate as(Predicate predicate) {    return predicate;}

通过使用一个静态方法,接受方法引用参数,返回一个函数接口,即可实现方法引用到函数接口的转换。接着,我们就可以使用方法引用来实现上面例子中的获取非空字符串的数目。

Stream.of("A", "", "B").filter(as(String::isEmpty).negate()).count();

进一步还能使用各种组合的Predicate。

.filter(as(String::isEmpty).negate().and("A"::equals))

由于一个方法引用可能会被解析为多种函数接口,因此如果我们实现很多参数不同的as方法,那么很容易造成混淆。更好的方式则是在方法名中加入函数参数的类型来区分。

mport java.util.function.*;

public class FunctionCastUtil {
    public static  BiConsumer asBiConsumer(BiConsumer biConsumer) {
        return biConsumer;
    }
    public static  BiFunction asBiFunction(BiFunction biFunction) {
        return biFunction;
    }
    public static  BinaryOperator asBinaryOperator(BinaryOperator binaryOperator) {
        return binaryOperator;
    }
    public static  BiPredicate asBiPredicate(BiPredicate biPredicate) {
        return biPredicate;
    }
    public static BooleanSupplier asBooleanSupplier(BooleanSupplier booleanSupplier) {
        return booleanSupplier;
    }
    public static  Consumer asConsumer(Consumer consumer) {
        return consumer;
    }
    public static DoubleBinaryOperator asDoubleBinaryOperator(DoubleBinaryOperator doubleBinaryOperator) {
        return doubleBinaryOperator;
    }
    public static DoubleConsumer asDoubleConsumer(DoubleConsumer doubleConsumer) {
        return doubleConsumer;
    }
    public static  DoubleFunction asDoubleFunction(DoubleFunction 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  Function asFunction(Function function) {
        return function;
    }
    public static IntBinaryOperator asIntBinaryOperator(IntBinaryOperator intBinaryOperator) {
        return intBinaryOperator;
    }
    public static IntConsumer asIntConsumer(IntConsumer intConsumer) {
        return intConsumer;
    }
    public static  IntFunction asIntFunction(IntFunction 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  LongFunction asLongFunction(LongFunction longFunction) {
        return longFunction;
    }
    public static LongPredicate asLongPredicate(LongPredicate longPredicate) {
        return longPredicate;
    }
    public static  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  ObjDoubleConsumer asObjDoubleConsumer(ObjDoubleConsumer objDoubleConsumer) {
        return objDoubleConsumer;
    }
    public static  ObjIntConsumer asObjIntConsumer(ObjIntConsumer objIntConsumer) {
        return objIntConsumer;
    }
    public static  ObjLongConsumer asObjLongConsumer(ObjLongConsumer objLongConsumer) {
        return objLongConsumer;
    }
    public static  Predicate asPredicate(Predicate predicate) {
        return predicate;
    }
    public static  Supplier asSupplier(Supplier supplier) {
        return supplier;
    }
    public static  ToDoubleBiFunction asToDoubleBiFunction(ToDoubleBiFunction toDoubleBiFunction) {
        return toDoubleBiFunction;
    }
    public static  ToDoubleFunction asToDoubleFunction(ToDoubleFunction toDoubleFunction) {
        return toDoubleFunction;
    }
    public static  ToIntBiFunction asToIntBiFunction(ToIntBiFunction toIntBiFunction) {
        return toIntBiFunction;
    }
    public static  ToIntFunction asToIntFunction(ToIntFunction ioIntFunction) {
        return ioIntFunction;
    }
    public static  ToLongBiFunction asToLongBiFunction(ToLongBiFunction toLongBiFunction) {
        return toLongBiFunction;
    }
    public static  ToLongFunction asToLongFunction(ToLongFunction toLongFunction) {
        return toLongFunction;
    }
    public static  UnaryOperator asUnaryOperator(UnaryOperator 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/

END

最近热文:

1、Redis 到底是单线程还是多线程?

2、Spring Boot 打包插件,真是太有用了!

3、用 float 存储金额,老板说损失从工资扣!

4、阿里发布《Java开发手册(泰山版)》

5、推荐一款 IDEA 代码神器,再也不加班了!

6、如何不重启热更新线上 Java 代码?

7、图解 Spring 循环依赖,写得太好了!

8、Java 14 来了,这回让空指针无处遁形!

9、一条垃圾SQL,把64核CPU快跑崩了!

10、百度开源的 71 个项目,太牛逼了!

公众号干货实在太多,扫码关注Java技术栈公众号阅读更多。

点击「阅读原文」带你飞~

你可能感兴趣的:(Java 8 中的方法引用,怎么用到最好?)