如何在Java中映射lambda表达式

6

我是从Python转来的,现在正在尝试理解Java中lambda表达式的不同之处。在Python中,您可以做如下操作:

opdict = { "+":lambda a,b: a+b, "-": lambda a,b: a-b, 
           "*": lambda a,b: a*b, "/": lambda a,b: a/b }
sum = opdict["+"](5,4) 

我该如何在Java中实现类似的功能?我已经阅读了一些关于Java lambda表达式的内容,似乎我需要先声明一个接口,但我不清楚为什么需要这样做以及如何实现。
编辑:我尝试使用自定义接口自己完成。下面是我尝试的代码:
Map<String, MathOperation> opMap = new HashMap<String, MathOperation>(){
        { put("+",(a,b)->b+a);
          put("-",(a,b)->b-a);
          put("*",(a,b)->b*a);
          put("/",(a,b)->b/a); }
};
...
...

interface MathOperation {
   double operation(double a, double b);
}

然而,这会出现错误:
目标类型必须是一个函数式接口。
我应该在哪里声明接口?
2个回答

8

在Java 8中,使用BiFunction很容易实现:

final Map<String, BiFunction<Integer, Integer, Integer>> opdict = new HashMap<>();
opdict.put("+", (x, y) -> x + y);
opdict.put("-", (x, y) -> x - y);
opdict.put("*", (x, y) -> x * y);
opdict.put("/", (x, y) -> x / y);

int sum = opdict.get("+").apply(5, 4);
System.out.println(sum);

语法比Python更冗长,使用opdict上的getOrDefault可能更可取,以避免使用不存在的运算符,但这至少可以让球滚动起来。

如果您仅使用int,则使用IntBinaryOperator将是更可取的选择,因为这将处理您必须执行的任何通用键入。

final Map<String, IntBinaryOperator> opdict = new HashMap<>();
opdict.put("+", (x, y) -> x + y);
opdict.put("-", (x, y) -> x - y);
opdict.put("*", (x, y) -> x * y);
opdict.put("/", (x, y) -> x / y);

int sum = opdict.get("+").applyAsInt(5, 4);
System.out.println(sum);

IntBinaryOperator 可能会稍微好一些。 - Paul Boddington
@PaulBoddington:是的,你肯定是对的,但是我们会遇到一个尴尬的情况:如果我们想要能够将不仅仅是整数的东西相加怎么办呢?不过我会包括你向我展示的内容,感谢你。 - Makoto
是的,这种情况可能很烦人。当我们最终获得 Map.of("+", (x, y) -> x + y, "-", ... 时,它将几乎与Python版本一样简短。 - Paul Boddington
很好的答案,只有一个后续问题;如果我想要实现自己的接口,我该怎么做?据我所知,当您使用lambda表达式实例化接口时,您基本上正在实现接口的抽象方法。请参见我对帖子所做的编辑。 - b_pcakes
@SimonZhu:当我使用你的自定义接口时,我没有注意到任何编译失败。我正在运行最新版本(我认为)的Java 1.8.60;请确保你也是最新的。 - Makoto

2

另一种解决方案是使用枚举:

public enum Operation {
    PLUS((x, y) -> x + y),
    MINUS((x, y) -> x - y),
    TIMES((x, y) -> x * y),
    DIVIDE((x, y) -> x / y);

    private final IntBinaryOperator op;

    Operation(IntBinaryOperator op) { this.op = op; }

    public int apply(int x, int y) { return op.applyAsInt(x, y); }
}

然后你可以这样做:
int sum = Operation.PLUS.apply(5, 4);

这不如其他解决方案简洁,但是使用枚举而不是 String 意味着当你在 IDE 中输入 Operation. 时,将显示所有可能操作的列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接