在Java 8中重用Lambda表达式

CKi*_*ing 1 lambda reusability java-8

Java 8允许您在不同的上下文中使用相同的lambda表达式。考虑下面的代码来演示这一点:

   public class LambdasTypeCheck {
        public static void main(String []args) {
            //Same lambda expression can be used in different contexts.
            Predicate<List<String>> predicate = (l) -> l.add("1");
            Consumer<List<String>>  consumer = (l) -> l.add("1");
        }
    }
Run Code Online (Sandbox Code Playgroud)

lambda表达式(l) -> l.add("1");在两个地方重复。如何避免这种重复?我可以重用此lambda表达式的一种方法是,是否有一些接口/类是所有lambda表达式的父级,这样我就可以将任何lambda表达式分配给此类接口/类的引用。

Hol*_*ger 5

您没有定义担心的“重复项”。

如果是代码重复(或者说,担心表达式之间可能存在的不一致本来应该是相同的)困扰着您,则可以使用

Predicate<List<String>> predicate = (l) -> l.add("1");
Consumer<List<String>>  consumer = predicate::test;
Run Code Online (Sandbox Code Playgroud)

避免它。

如果希望lambda表达式真正由同一实例表示,则可以创建一个合并的interface

interface PredicateAndConsumer<T> extends Predicate<T>, Consumer<T> {
    public default void accept(T t) { test(t); }
}
Run Code Online (Sandbox Code Playgroud)

 

PredicateAndConsumer<List<String>> pAndC = (l) -> l.add("1");
Predicate<List<String>> predicate = pAndC;
Consumer<List<String>>  consumer = pAndC;
Run Code Online (Sandbox Code Playgroud)

因此,如您所见,可以pAndC在需要Predicate<List<String>>或的两种情况下使用Consumer<List<String>>

但是,这样做几乎没有好处。在这种特殊情况下,我们可以安全地假设,对于大多数JRE,引入另一个JRE的开销interface要比通过一个Lambda表达式实现它的开销要高。


您还可以考虑以下答案:“ Java 8中方法引用缓存是个好主意吗?”。概括地说,您的示例表达式不会捕获值,因此将在Oracle参考实现中作为单例实现(并且在所有其他实现中也可能会如此)。因此,这里我们要讨论的是在运行时环境中创建的是一个还是两个不变的常量……