使您的Java 8方法引用生效
方法参考
众所周知,我们可以使用Java 8中的方法引用 (例如String::isEmpty
来引用例如在元素上流式传输时使用的方法。 看一下以下代码片段:
Stream.of("A", "", "B").filter(Stream::isEmpty).count();
它将产生结果1(因为流中只有一个空元素)。 但是,如果要过滤掉非空字符串,则需要编写.filter(s -> !s.isEmpty())
,这是一个Lambda。 显然,这里有一个令人讨厌的不对称。 我们可以使用方法参考,但不能使用它的否定。 我们可以编写predicate.negate()
但不能编写Stream::isEmpty.negate()
或!Stream::isEmpty
。
这是为什么? 这是因为方法引用不是Lambda或功能接口。 但是,可以使用Java的类型推断将方法引用解析为一个或多个功能接口。 实际上,我们的示例String::isEmpty
至少可以解析为:
Predicate<String>
Function<String, Boolean>
因此,我们需要以某种方式解决所有潜在的歧义,并确定我们要将方法参考转换为哪个功能接口。 阅读这篇文章,了解如何部分解决此问题。 我使用了开源项目Speedment中提供的代码,该代码使数据库看起来像Java 8 Streams。 随意尝试Speedment out。
Speedment还包含谓词生成器,使您可以直接使用诸如Entity.NAME::isEmpty和Entity.NAME::isNotEmpty之类的函数。
解析方法参考
通过以静态方法的形式引入一些“管道”,可以部分解决该问题,该方法采用“方法参考”并将其作为特定功能接口的视图返回。 考虑以下简短的静态方法:
public static <T> Predicate<T> as(Predicate<T> predicate) {return predicate;}
现在,如果我们静态导入该方法,实际上,我们可以更轻松地使用“方法引用”,如以下简短示例所示:
Stream.of("A", "", "B").filter(as(String::isEmpty).negate()).count();
该代码将返回2,这是流中非空元素的数量。 在方法参考用法方面,这是向前迈出的一步。 另一个好处是,此解决方案使我们可以更轻松地组成谓词,如下所示:
.filter(as(String::isEmpty).negate().and("A"::equals))
解决所有方法参考
但是,我们仍然需要解决一个问题。 我们不能简单地开始创建很多静态的as()
函数,因为方法引用可能可以用本文开头列出的相同方式解析为几种潜在的as()
方法。 因此,更好的方法是将功能接口类型名称附加到每个静态方法,从而使我们能够以编程方式选择特定的方法参考到功能接口转换方法。 这是一个实用程序类,它允许将方法引用转换为驻留在标准Java包java.util.function
中的任何匹配的Functional Interface。
- 在此处直接从GitHub下拉最新版本
import java.util.function.*;/**** @author Per Minborg*/
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();
更好的解决方案
如果所有功能接口本身都包含一个静态方法,该方法可以采用适当的“方法引用”并将其转换为类型化的功能接口,那将更好。 例如,标准的Java Predicate
功能接口将如下所示:
@FunctionalInterface
public interface Predicate<T> {boolean test(T t);default Predicate<T> and(Predicate<? super T> other) {...}default Predicate<T> negate() {...}default Predicate<T> or(Predicate<? super T> other) {...}static <T> Predicate<T> isEqual(Object targetRef) {...}// New proposed support method to return a // Predicate view of a Functional Reference public static <T> Predicate<T> of(Predicate<T> predicate) {return predicate;}}
这将使我们能够编写:
Stream.of("A", "", "B").filter(Predicate.of(String::isEmpty).negate()).count();
我个人认为看起来不错!
与您最近的Open JDK开发人员联系并提出建议!
翻译自: https://www.javacodegeeks.com/2016/03/put-java-8-method-references-work.html
使您的Java 8方法引用生效相关推荐
- java set方法不生效_使您的Java 8方法引用生效
java set方法不生效 方法参考 众所周知,我们可以使用Java 8中的方法引用 (例如String::isEmpty来引用例如在元素上流式传输时使用的方法. 看一下以下代码片段: Stream. ...
- Java中 方法引用、Stream流、及方法实例 D190401
Java中 方法引用.Stream流.及方法实例 D190401 01.第三章:方法引用_什么是方法引用 1).什么是"方法引用":指引用现有的方法代替Lambda表达式--当我们 ...
- java(九)-方法引用, Stream流,File类 , 递归 ,字节流
day09[方法引用.Lambda表达式.Stream流] 今日目标 线程状态 等待与唤醒 Lambda表达式 Stream流 教学目标 能够说出线程6个状态的名称 能够理解等待唤醒案例 能够掌握La ...
- java 8 方法引用(method references)
1 什么是方法引用(method references) java 8 添加了一个很熟悉但是又很陌生的符号::. 你也许会看到这样的代码 System.out::println 其实就是方法引用(me ...
- [Java基础]方法引用
代码如下: package PrintablePack;public interface Printable {void printString(String s);} package Printab ...
- Effective Java~43. 方法引用优于Lambda
Java 提供了一种生成函数对象的方法,比 lambda 还要简洁,那就是:方法引用( method references).下面是一段程序代码片段,它维护一个从任意键到整数值的映射.如果将该值解释为 ...
- Java 8 方法引用 (Method Reference)快速介绍与示例
Method Reference 是什么? Method Reference 是Java 8 才开始提供的新特性, 翻译过来是方法引用. 其定义就是: 把已经定义好的名字和方法, 当做Lambda 表 ...
- 秒懂Java之方法引用(method reference)详解
[版权申明]非商业目的注明出处可自由转载 博文地址:https://blog.csdn.net/ShuSheng0007/article/details/107562812 出自:shusheng00 ...
- Java主方法引用传递_java方法中的参数传递是值传递还是引用传递(转)
1.当参数变量为基本数据类型或者字符串时: ... ... //定义了一个改变参数值的函数 public static void changeValue(int x) { x = x *2; } .. ...
最新文章
- 从Linux内核中获取真随机数【转】
- SQLite单例模式(QT4)
- LibreOJ - 3083 与或和(单调栈+位运算)
- context set_parameter all_req_parameters /iwfnd/if_sodata_types=gcs_iwf_context
- 灯泡四个闪烁c语言程序设计教程课后答案,c语言编程题及答案4.doc
- win10无法运行C语言文件,主编告诉你win10打不开pdf文件的详尽处理办法
- Linux中存储相关的命令,Linux存储管理命令与HAB相关命令
- Linux服务器配置秘钥对连接
- 社区团购真的是实体店终结者吗?
- crontab 简介
- 在你的Android上执行Linux命令
- CISCO 模拟器 Dynamips 使用说明
- 制作数据分析报告的公开数据集资源
- 生成对抗网络训练_生成对抗网络
- idea中编译DataSphereStudio编译方法及问题排查
- 像素排列 p(Pentile)排列 RGB 排列
- linux挂死oops定位问题
- 大图数据管理与分析技术(综述)
- HBase java 的增删改查
- 深圳打卡(四) 红树林与深圳湾公园
热门文章
- Java 必看的 Spring 知识汇总
- System.gc()调用 - 适用的场景
- jQuery选择器案例之——index.js
- ArrayList基操
- Mybatis中使用Dao实现类实现增删改查【实际开发中使用代理dao】
- Error:(1, 10) java: 需要class, interface或enum
- win10系统excel2019单元格显示完整的年月日时分秒设置方法
- 大神开发的模板框架 包括常见的功能
- java凯撒密码_JAVA凯撒密码 选择问题
- 转移指令jmp和跳转指令call