Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 817
Shivansh Kuchhal Avatar asked Aug 25 '18 08:08

Shivansh Kuchhal


People also ask

Can Lambda functions be used to iterate through a list?

First off, the Lambda function itself cannot be used to iterate through a list. Lambda, by its very nature, is used to write simple functions without the use of defining them beforehand.

Is lambda function faster than for loop?

The answer is it depends. I have seen cases where using a lambda was slower and where it was faster. I have also seen that with newer updates you get more optimal code.

What is lambda expression in Java 8?

The lambda expressions are inline code that implements a functional interface without creating an anonymous class. In Java 8, forEach statement can be used along with lambda expression that reduces the looping through a Map to a single statement and also iterates over the elements of a list.

How to store a lambda expression in a variable?

The lambda expression should have the same number of parameters and the same return type as that method. Java has many of these kinds of interfaces built in, such as the Consumer interface (found in the java.util package) used by lists. Use Java's Consumer interface to store a lambda expression in a variable:

What is external iteration in Java?

Doing this way, we take each element out of the collection for iterating from the first to the end. Thus it is called “external iteration”. We know that in Java, all the collection interfaces (List, Set, Queue, etc) have the Iterable as their super interface. And since Java 8, the Iterable interface introduces a new method:

How do I print every item in a list using lambda expressions?

Lambda expressions are usually passed as parameters to a function: Use a lamba expression in the ArrayList 's forEach () method to print every item in the list: Lambda expressions can be stored in variables if the variable's type is an interface which has only one method.


2 Answers

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)));
like image 172
YCF_L Avatar answered Oct 20 '22 00:10

YCF_L


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;
like image 30
Boris the Spider Avatar answered Oct 20 '22 00:10

Boris the Spider