Skip to content
Advertisement

How to apply Direct function in Stream.map() like in JavaScript

Have a question, when I use a stream map in Java I have to be explicit with the lambda. Suppose I have this mapper function:

public static Integer mapFunction(Integer number){
    return number + 3;
}

And then I want to apply it to a certain List, I have to do this:

myList.stream().map(element -> mapFunction(element))

So my question is if I can do something similar to what can be done in JavaScript, like

myList.map(mapFunction)

Like pass the function directly to it without having explicitly tell it to do it for each element.

Thanks in advance!

Advertisement

Answer

Stream.map() in Java is not an equivalent of Array.map() in JavaScript, which immediately produces another array (dynamic array).

Streams

Firstly, there’s a notion of Stream which is a sequence of elements supporting sequential and parallel aggregate operations. It’s not a container of data, but the mean of iteration.

A Stream has a source, can potentially have some intermediate operations (they are optional), and a single terminal operation, which triggers the execution of the stream.

A stream-source can be a collection or an array, a string, or a generator function like Random.ints(). During stream execution, elements are being lazily from the source one by one and each operation in the stream pipeline would be applied on a particular element only if it’s needed.

map() – is an intermediate operation, i.e. produces another stream – Stream<R>. It’s mean to transform the elements of the stream and expects a function that does this transformation, but doesn’t produce the result.

In order to obtain the result, we need to apply a terminal operation, i.e. an operation that consumes a stream and produces a value. To generate a list from the result, we have two options: apply collect() by passing a built-in collector toList() as an argument, or make use of Java 16 method toList() which produces an immutable list.

Java Functions

As well as methods in Java are not completely as functions in JavaScript where they first class citizens (Java methods are not), Java 8 functions are not the same as methods.

Java 8 functions can be expressed either as Lambda expressions or Method references.

In short, there’s no same kind of functional type, instead we have a notion of a Functional interface, which is an interface that has only one abstract method. And both lambda expressions and method references should conform to a functional interface, i.e. they provide implementation to a particular functional interface.

So there are two ways in which you can create your Function.

As a lambda:

Function<Integer, Integer> func = i -> mapFunction(i);

Or as a method reference (since you have this functionality already implemented as a method).

If method mapFunction() is static:

Function<Integer, Integer> func = ClassName::mapFunction; // 

Where ClassName is the name of a class in which mapFunction() method resides.

In case if mapFunction() is an instance method:

Function<Integer, Integer> func = objectName::mapFunction;

Where objectName is the name of an instance of a class in which mapFunction() method resides.

And the overall stream pipeline would look like that:

List<Integer> result = numbers.stream()
    .map(ClassName::mapFunction)     // or `objectName::mapFunction` if `mapFunction()` is an instance method
    .collect(Collectors.toList());   // or `.toList()` for Java 16+
Advertisement