I'm coming from Python, and trying to understand how lambda expressions work differently in Java. In Python, you can do stuff like:
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)
How can I accomplish something similar in Java? I have read a bit on Java lambda expressions, and it seems I have to declare an interface first, and I'm unclear about how and why you need to do this.
Edit: I attempted to do this myself with a custom interface. Here's the code I have tried:
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);
}
However, this gives an error:
The target type of this expression must be a functional interface.
Where exactly do I declare the interface?
A Map is a collection object that maps keys to values in Java. The data can be stored in key/value pairs and each key is unique. These key/value pairs are also called map entries.
A Map is an object that maps keys to values. A map cannot contain duplicate keys: Each key can map to at most one value. It models the mathematical function abstraction.
Java 8 Stream's map method is intermediate operation and consumes single element forom input Stream and produces single element to output Stream. It simply used to convert Stream of one type to another.
Easy enough to do with a BiFunction
in Java 8:
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);
The syntax is a bit more verbose than Python to be sure, and using getOrDefault
on opdict
would probably be preferable as to avoid a scenario in which you use an operator that doesn't exist, but this should get the ball rolling at least.
If you're exclusively working with int
s, using IntBinaryOperator
would be preferable, as this would take care of any generic typing that you'd have to do.
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);
An alternative solution is to use an enum:
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); }
}
Then you can do:
int sum = Operation.PLUS.apply(5, 4);
This is not as succinct as other solutions, but using an enum rather than a String
means that when you type Operation.
into an IDE, you will be presented with the list of all possible operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With