Reputation: 21443
Java 8 added lambda expressions. Using lambdas in a similar fashion to anonymous classes is pretty straight forward, but I'm wondering if the related functionality of using named functions as arguments to other functions exists. For example, is there a Java way to write the following Python code:
list1 = (1,2,3)
list2 = (4,5,6)
def add(a, b):
return a+b
for e in map(add, list1, list2):
print(e)
output
5
7
9
Upvotes: 5
Views: 1716
Reputation: 132350
It's certainly possible to declare variables whose types are functional interfaces and then assign lambdas to them. That's the conclusion of this answer and its comment thread. For example, one might have a declaration like this:
BiFunction<Integer,Integer,Integer> add = (a, b) -> a + b;
This isn't exactly what the OP asked for. The Python equivalent of this would be something like:
add = lambda a, b: a + b
This isn't a named function; it's a variable whose value is a (lambda) function. The original question was asking about using named function in Java. The way to do this is with a method reference.
Suppose you have method that takes a BiFunction<Integer,Integer,Integer>
parameter. You could pass it the add
variable as defined above. But you could also declare an ordinary method, and use it as the target of a method reference. The trick is to make sure that the "shape" (number and type of arguments, type of return value) matches whatever functional interface you're trying to use. In this case you have two parameters of type Integer
and the return value is Integer
, so your method would be
static Integer add(Integer a, Integer b) {
return a + b;
}
Then you can refer to this using a method reference of the form MyClass::add
.
Note that I've made this a static method. If it were an instance method, the receiver (this
) is a hidden parameter that you have to take into account when matching it to a functional interface.
Note also that because of auto-boxing, one could also write:
static int add(int a, int b) {
return a + b;
}
There's certainly a use for assigning lambdas to variables, such as if the choice of an algorithm is made at runtime. But if the lambdas are all being assigned to constant fields, it's often easier to use method references that target ordinary methods.
Upvotes: 0
Reputation: 47249
Well, there are no "functions" in Java, only methods, so you would not get the same exact thing.
The best way to achieve this is to use method references, and in this case a BiConsumer
could be used:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
public class StackOverflow {
public static void main(String[] args) throws InterruptedException {
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
List<Integer> list2 = new ArrayList<>();
list2.add(4);
list2.add(5);
list2.add(6);
mapOver(StackOverflow::add, list1, list2);
}
public static void add(Integer a, Integer b) {
System.out.println(a + b);
}
public static <T> void mapOver(BiConsumer<T, T> function,
Iterable<T> first,
Iterable<T> second) {
final Iterator<T> firstIterator = first.iterator();
final Iterator<T> secondIterator = second.iterator();
while (firstIterator.hasNext() && secondIterator.hasNext()) {
function.accept(firstIterator.next(), secondIterator.next());
}
}
}
Output:
5
7
9
Upvotes: 2
Reputation: 361565
Yes, you can use method references like Integer::sum
where lambdas are allowed.
int six = IntStream.of(1, 2, 3)
.reduce(0, Integer::sum);
This is equivalent to
int six = IntStream.of(1, 2, 3)
.reduce(0, (a, b) -> Integer.sum(a, b));
Methods like Integer.sum
and Double.max
were added in Java 8 precisely so they could be used in lambdas like this.
There's no built-in way to "zip" together multiple lists the way Python does, though.
Upvotes: 4
Reputation: 695
Not sure what your question really is, but in Java, this would be something like..
List<Integer list1 = Arrays.asList(1,2,3);
List<Integer list2 = Arrays.asList(4,5,6);
IntStream.range(0, list1.size())
.parallel()
.forEach(i -> {
System.out.println(list1.get(i) + list2.get(i));
});
.. since you can't stream multiple collections in Java as you can in python.
Upvotes: 0