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?





Java is only a very tiny bit more verbose
– Walter Tross
Aug 25 at 9:08





except that in python AFAIK lambdas are limited to a single statement, right?
– Eugene
Aug 25 at 12:00





@Eugene Actually, in Python lambdas 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.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)