How to iterate over lambda functions in Java

I was able to do it in Python and my Python code is:

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))


And the output is:

8
2


How do I do this same thing in Java through HashMap?

You can use BinaryOperator<Integer> in this case like so :

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)));


Outputs

8
2




Note for Map.of("+", add, "-", sub); I'm using Java 10, If you are not using Java 9+ you can add to your map like so:

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


Ideone demo



Good practice

As already stated by @Boris the Spider and @Holger in the comments, Its better to use IntBinaryOperator to avoid boxing, in the end your code can look like this :

// 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)));


Create yourself a nice, typesafe, 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);
}
}


You may want a lambda that returns double rather than int for other operators.

Now, simply dump that into a Map:

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


For your example though, you don't need a Map at all:

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




Using:

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

Comments

Popular posts from this blog

Meaning of `{}` for return expression

Get current scroll position of ScrollView in React Native

flutter websocket connection issue