【问题标题】:Java Lambdas: Sending method name as parameterJava Lambdas:将方法名称作为参数发送
【发布时间】:2017-09-01 23:49:33
【问题描述】:

我遇到了一个问题,我的类包含多个方法和大量重复代码。这背后的原因是每个方法都会遍历一个条目列表并调用特定的条目方法。

在代码中...

LowLevelClass 类的结构如下:

public class LowLevelClass {

    // constructor omitted

    public boolean doSomethingA() {
        // some non-duplicated code
        return true;
    }

    public boolean doSomethingB() {
        // some non-duplicated code
        return true;
    }

    public boolean doSomethingC() {
        // some non-duplicated code
        return true;
    }
}

顶级类包含一个LowLevelClasses列表,方法数量相同,但这次有很多重复:

public class HighLevelClass {

    private List<LowLevelClass> classes = new ArrayList<>();

    public HighLevelClass() {
        this.classes.add(new LowLevelClass(/* params */));
        this.classes.add(new LowLevelClass(/* params */));
        this.classes.add(new LowLevelClass(/* params */));
    }

    public void doA() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingA();
            System.out.println("Done");
        }
    }

    public void doB() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingB();
            System.out.println("Done");
        }
    }

    public void doC() {
        System.out.println("Doing ...");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.doSomethingC();
            System.out.println("Done");
        }
    }
}

我的目标是拥有以下形式的东西:

public class HighLevelClass {

    private List<LowLevelClass> classes = new ArrayList<>();

    public HighLevelClass() {
        this.classes.add(new LowLevelClass());
        this.classes.add(new LowLevelClass());
        this.classes.add(new LowLevelClass());
    }

    public void doSomething(Lambda /* Functional interface*/ operation) {
        System.out.println("Doing A");
        for (LowLevelClass entry : classes) {
            System.out.println("Doing something...");
            entry.operation; // or something else...
            System.out.println("Done");
        }
    }

    public void doSomethingA() {
        // my goal... and maybe in totally wrong direction is to send something in form of...
        return doSomething(LowLevelClass::doSomethingA);
    }

    // etc
}

这可以用 Lambda 在 Java 8 中完成吗?换句话说,我可以定义对给定列表的每个条目执行的方法吗?

编辑 1

Jorn VerneeJoffrey 提供的答案是正确的!

最终,解决方案是使用 Predicate。 (见 EDIT 2 为什么我最后没有使用 Consumer...)

公共类 HighLevelClass {

private List<LowLevelClass> classes = new ArrayList<>();

public HighLevelClass() {
    this.classes.add(new LowLevelClass());
    this.classes.add(new LowLevelClass());
    this.classes.add(new LowLevelClass());
}

public boolean doSomething(Predicate<LowLevelClass> function) {
    System.out.println("Doing A");
    for (LowLevelClass entry : classes) {
        System.out.println("Doing something...");
        boolean val = function.test(entry);
        System.out.println("Done " + val);
    }
    return someEndVerdict; 
}

public boolean doSomethingA() {
    return doSomething(LowLevelClass::doSomethingA);
}

// etc

}

编辑 2

我在 HighLevelClass 中的初始方法不包含布尔返回类型。这就是我使用谓词的原因(谓词,作为消费者的一个对照,返回更适合我的布尔值 - 我最初忘记提到了:((()

感谢您的帮助和时间!

【问题讨论】:

  • 喜欢list.stream().forEach()?
  • 为什么必须是 lambda。为什么不能传入任何类型的函数指针?
  • 为什么不呢?您是否尝试过合适的功能接口类型?喜欢Comsumer&lt;LowLevelClass&gt;
  • 您的解决方案看起来不错。你被困在哪里了?
  • @xanmcgregor 你没有使用你的谓词的返回值,这对我来说看起来不对。

标签: java lambda interface functional-programming


【解决方案1】:

您不应该混淆您调用方法的方式(可能涉及也可能不涉及 lambda)和您编写方法的方式(涉及找到正确的方法)参数类型。

在编写方法时,您需要关注参数的类型。如果其中一个是表示函数的对象,您需要了解该函数应匹配的适当签名,这将为您提供应作为参数类型放置的功能接口。

在您的情况下,您期望一个函数接受 1 个 LowLevelClass 类型的参数并且不返回任何值。您可能对此感到惊讶,但您需要将实例方法视为将类 (this) 的实例作为额外的第一个参数(与静态方法相反)的函数。

因此,Consumer&lt;LowLevelClass&gt; 接口就是你想要的:

public void doSomething(Consumer<LowLevelClass> operation) {
    System.out.println("Doing A");
    for (LowLevelClass entry : classes) {
        System.out.println("Doing something...");
        operation.accept(entry); // or something else...
        System.out.println("Done");
    }
}

public void doSomethingA() {
    return doSomething(LowLevelClass::doSomethingA);
}

【讨论】:

  • 这是正确答案。另外,我忘了输入返回值。这最终导致我选择了 Predicated 而不是 Consumer。无论如何,解释都是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-09
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多