【问题标题】:How to iterate over lambda functions in Java如何在 Java 中迭代 lambda 函数
【发布时间】:2018-08-25 08:39:24
【问题描述】:

我能够在 Python 中做到这一点,我的 Python 代码是:

signs = {"+" : lambda a, b : a + b, "-" : lambda a, b : a - b}

a = 5
b = 3
for i in signs.keys():
    print(signs[i](a,b))

输出是:

8
2

我如何通过 HashMap 在 Java 中做同样的事情?

【问题讨论】:

  • Java 只是稍微冗长一点
  • 除了在 python AFAIK 中,lambda 被限制为 single 语句,对吧?
  • @Eugene 实际上,在 Python 中,lambdas 仅限于没有语句。只允许使用表达式。
  • @WalterTross 哎呀。值是文字,不是吗? :-/
  • 文字是值,反之则不然。

标签: java python lambda java-8 java-stream


【解决方案1】:

在这种情况下,您可以像这样使用BinaryOperator<Integer>

BinaryOperator<Integer> add = (a, b) -> a + b;//lambda a, b : a + b
BinaryOperator<Integer> sub = (a, b) -> a - b;//lambda a, b : a - b

// Then create a new Map which take the sign and the corresponding BinaryOperator
// equivalent to signs = {"+" : lambda a, b : a + b, "-" : lambda a, b : a - b}
Map<String, BinaryOperator<Integer>> signs = Map.of("+", add, "-", sub);

int a = 5; // a = 5
int b = 3; // b = 3

// Loop over the sings map and apply the operation
signs.values().forEach(v -> System.out.println(v.apply(a, b)));

输出

8
2

注意Map.of("+", add, "-", sub); 我使用的是 Java 10,如果你没有使用 Java 9+,你可以像这样添加到你的地图中:

Map<String, BinaryOperator<Integer>> signs = new HashMap<>();
signs.put("+", add);
signs.put("-", sub);

Ideone demo


良好做法

正如@Boris the Spider@Holger 在cmets 中已经说过的,最好使用IntBinaryOperator 来避免装箱,最终您的代码可以如下所示:

// signs = {"+" : lambda a, b : a + b, "-" : lambda a, b : a - b}
Map<String, IntBinaryOperator> signs = Map.of("+", (a, b) -> a + b, "-", (a, b) -> a - b);
int a = 5; // a = 5
int b = 3; // b = 3
// for i in signs.keys(): print(signs[i](a,b))
signs.values().forEach(v -> System.out.println(v.applyAsInt(a, b)));

【讨论】:

  • 谢谢@BoristheSpider 我之前没有和IntBinaryOperator 合作过,我会了解这个的,我看到你的回答,发现你已经在使用它+1
  • 它是 (int, int) -&gt; int 而不是 Integer - 所以拳击更少。不过你的回答很好 - +1!
  • 如果你使用的是java 10,可以将地图定义为var signs = Map.of("+", add, "-", sub);
  • 这是正确的@FedericoPeraltaSchaffner 使其不带 var 以使其对 OP 更具可读性:)
  • 即使是装箱值,您也可以在此处使用BinaryOperator&lt;Integer&gt;,它是BiFunction&lt;Integer, Integer, Integer&gt; 的子类型。此外,您不需要为函数详细声明局部变量:Map&lt;String, BinaryOperator&lt;Integer&gt;&gt; signs = Map.of("+", (a, b) -&gt; a + b, "-", (a, b) -&gt; a - b);;这更接近于 OP 的 Python 代码。当然,只要用例允许使用 IntBinaryOperator 代替,它就更可取,因为它避免了装箱开销(甚至比 BinaryOperator&lt;Integer&gt; 更短)……
【解决方案2】:

为自己创建一个漂亮、类型安全的enum

enum Operator implements IntBinaryOperator {
    PLUS("+", Integer::sum),
    MINUS("-", (a, b) -> a - b);

    private final String symbol;
    private final IntBinaryOperator op;

    Operator(final String symbol, final IntBinaryOperator op) {
        this.symbol = symbol;
        this.op = op;
    }

    public String symbol() {
        return symbol;
    }

    @Override
    public int applyAsInt(final int left, final int right) {
        return op.applyAsInt(left, right);
    }
}

对于其他运算符,您可能需要一个返回 double 而不是 int 的 lambda。

现在,只需将其转储到 Map

final var operators = Arrays.stream(Operator.values())
        .collect(toMap(Operator::symbol, identity()));

不过,对于您的示例,您根本不需要 Map

Arrays.stream(Operator.values())
        .mapToInt(op -> op.applyAsInt(a,b))
        .forEach(System.out::println);

使用:

import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2020-11-20
    • 2022-11-03
    • 2012-01-29
    • 2014-09-01
    • 1970-01-01
    相关资源
    最近更新 更多