Explain Codes LogoExplain Codes Logo

Java: Is There a Map Function?

java
lazy-collections
functional-programming
stream-api
Alex KataevbyAlex Kataev·Jan 26, 2025
TLDR

Indeed, stream().map() combo in Java fills the shoes of the typical map function usually found in other programming languages. Need a quick showcase? Let's take a list of integers and double every element:

List<Integer> doubled = Arrays.asList(1, 2, 3).stream().map(x -> x * 2 /*Welcome to the twofold universe!*/).collect(Collectors.toList());

Notice x -> x * 2: this lambda expression doubles each integer, the stream then packs these revamped values into a brand new list. If you need those values in an array or a different collection type? There's always .toArray() or collect methods for your rescue, such as Collectors.toSet().

Stream API and Its Cousins

Java 8 streams are great, but they're are not the only game in town. Let's broaden the horizons and gaze at the territory beyond standard Java.

Java Transformers: Revenge of the Guava

For those who have been harnessing the power of Guava, a library by Google, there's Collections2.transform() functionality.

List<String> transformed = Collections2.transform(originalList, Functions.toStringFunction());

The plot twist here is that Guava is quite lazy, in a good sense, because it doesn't start the transformation until the pre-transformed (a.k.a "raw") values are actually fetched.

Java: The Final Frontier

Advanced Java developers might yearn for more. That's when Functional Java or the totallylazy library come into play. They introduce you to the world of fully lazy collections and a bouquet of functional methods.

Sequence<Integer> lazyMapped = sequence(asList(1, 2, 3)).map(multiplyBy(2) /*because 2 is lonely and needs companions*/);

Java 8, however, provides enough functionality for most cases, making separate libraries feel like luxury choices rather than necessities.

Custom Map Implementations to the Rescue

Embarking on your own map implementation can be an educational quest or a last resort due to performance issues or specific operations not available in the standard API or additional libraries.

Getting Crafty with stream().map()

Stream map() can be your creative outlet. Open the doors for complex operations and wave goodbye to yawn-inducing transformations:

Parsing or Formatting Data

Transforming between data types is a common task in any software, and thankfully as easy as saying "123":

List<String> strings = List.of("1", "2", "3"); List<Integer> integers = strings.stream().map(Integer::parseInt /*No strings attached. Literally.*/).collect(Collectors.toList());

Integrating Multiple Streams

When the streams join forces, they forge a smoother multitasking experience:

Stream.concat(stream1.map(func1), stream2.map(func2));

Powering Up with Parallel Streams

In computationally demanding scenarios, opt for parallelStream():

List<String> processed = largeList.parallelStream().map(expensiveFunction /*Running on the Java-fueled steroids*/).collect(Collectors.toList());

Just don't go overboard with parallel streams: It can lead to unexpected results when the operations have side effects or the data structures aren't corruption-proof in the multi-threaded environment.