本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。
Java 8方法引用使用指南(java dataoutputstream乱码)
方法引用
众所周知,在Java 8中我们可以使用方法引用。譬如,在我们需要遍历流元素时,可以使用 String::isEmpty 来引用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至少可以解析为:
PredicateFunction
解析方法引用
其实,以静态方法为“管道”,可以部分地解决这个问题——该静态方法以一个方法引用为输入,以特定的函数接口为其返回。试考虑下面这个简短的静态方法:
public static Predicate as(Predicate predicate) { return predicate;}
现在,如果静态地导入这个方法,事实上,我们就能更简单地使用方法引用。如下例所示:
Stream.of("A", "", "B").filter(as(String::isEmpty).negate()).count();
这段代码返回的结果为2,即流中非空元素的数量。有关方法引用的使用方式,我们又向前迈进了一步。另一个好处是,这个解决方案让我们更轻松地编写predicates接口,例如:
.filter(as(String::isEmpty).negate().and("A"::equals))
解析所有方法引用
但是,现在仍有一个问题亟待解决。我们不能随随便便地创建一大堆静态as()函数,因为一个方法引用可能解析为多种as()方法,正如本文开头提到的那样。所以,一个更妙的解决方案,是把函数接口类型名添加至每个静态方法,这样我们就可以程序化地为每个函数接口转换方法选择一个特定的方法引用。我们有一个工具类,可以让每个方法引用都转换为Java标准包 `java.util.function中任意匹配的函数接口。
import java.util.function.*;/** * * @author Per Minborg */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();
一个更好的解决方案
如果函数接口本身就包含一个接收方法引用并将其转换为某类函数接口的静态方法,那就更好了。举例来说,标准的Java Predicated函数接口就会变成这样:
@FunctionalInterfacepublic interface Predicate { boolean test(T t); default Predicate and(Predicate super T> other) {...} default Predicate negate() {...} default Predicate or(Predicate super T> other) {...} static Predicate isEqual(Object targetRef) {...} // New proposed support method to return a // Predicate view of a Functional Reference public static Predicate of(Predicate predicate) { return predicate; }}
因此,我们可以这样写:
Stream.of("A", "", "B").filter(Predicate.of(String::isEmpty).negate()).count();
笔者觉得这样看起来好极了!
快联系离你最近的Open JDK开发人员,提出你的修改建议吧!
暂时没有评论,来抢沙发吧~