How to iterate over lambda functions in Java
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?
except that in python AFAIK lambdas are limited to a single statement, right?
– Eugene
Aug 25 at 12:00
@Eugene Actually, in Python
lambda
s are limited to no statements at all. Only expressions are allowed.– wizzwizz4
Aug 25 at 15:28
lambda
@WalterTross Oops. Values are literals, aren't they? :-/
– wizzwizz4
Aug 25 at 15:31
Literals are values, but not vice versa.
– Midnightas
Aug 25 at 18:41
2 Answers
2
You can use BinaryOperator<Integer>
in this case like so :
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)));
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.of("+", add, "-", sub);
Map<String, BinaryOperator<Integer>> signs = new HashMap<>();
signs.put("+", add);
signs.put("-", sub);
Ideone demo
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 :
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)));
IntBinaryOperator
is probably a better choice...– Boris the Spider
Aug 25 at 8:47
IntBinaryOperator
Thank you @BoristheSpider I don't work with
IntBinaryOperator
before, I will learn about this, I see your answer and find that you already using it +1– YCF_L
Aug 25 at 8:55
IntBinaryOperator
It's
(int, int) -> int
rather than Integer
- so less boxing. Your answer is good though - +1!– Boris the Spider
Aug 25 at 8:56
(int, int) -> int
Integer
If you're using java 10, it's OK to define the map as
var signs = Map.of("+", add, "-", sub);
– Federico Peralta Schaffner
Aug 25 at 22:31
var signs = Map.of("+", add, "-", sub);
Even with boxed values, you can use
BinaryOperator<Integer>
here, which is a subtype of BiFunction<Integer, Integer, Integer>
. Further, you don’t need to verbosely declare local variables for the functions: Map<String, BinaryOperator<Integer>> signs = Map.of("+", (a, b) -> a + b, "-", (a, b) -> a - b);
; this is much closer to the OP’s Python code. Of course, whenever the use case allows to use IntBinaryOperator
instead, it’s preferable, as it avoids boxing overhead (and is even shorter than BinaryOperator<Integer>
)…– Holger
Aug 27 at 8:30
BinaryOperator<Integer>
BiFunction<Integer, Integer, Integer>
Map<String, BinaryOperator<Integer>> signs = Map.of("+", (a, b) -> a + b, "-", (a, b) -> a - b);
IntBinaryOperator
BinaryOperator<Integer>
Create yourself a nice, typesafe, enum
:
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.
double
int
Now, simply dump that into a Map
:
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:
Map
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;
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Java is only a very tiny bit more verbose
– Walter Tross
Aug 25 at 9:08