Java 8 Map

Next up in our series exploring functional programming in java 8, the map method.

Getting started

The map method is a transform operation and is a functional programming technique that applies a function to each one of a streams elements returning the results. A common use case map is utilized for is transforming object in java.

Starting simple

For our first snippet, lets multiply each element in the list by 10 by passing in a lambda function to the Stream.map() that accepts a parameter then multiples it by 10. Next, to display the results by using java8 print stream.

@Test
public void map_times_10() {

    List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);

    Stream<Integer> multipleOf10 = myList.stream().map((x) -> x * 10);

    multipleOf10.forEach(System.out::println);
}

Output

10
20
30
40
50

To be more usable, we can refactoring our code by moving the lambda expression and declare a function. In addition, if we were returning a list as a data type, we can convert the stream to list and then again, output the values in the list where we should see the same result as above.

@Test
public void map_times_10_refactor() {

    List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
    Function<Integer, Integer> times10 = (x) -> x * 10;

    List<Integer> multipleOf10 = myList.stream().map(times10)
            .collect(Collectors.toList());

    multipleOf10.forEach(System.out::println);
}

Output

10
20
30
40
50

Squaring values

Similar in fashion, lets create a function that will square all the values within a stream. We will create a java 8 function that accepts one parameter and then multiplies it by itself. Next we will Stream.collect(), a reduction operation, the result of the map and convert the stream to a set.

@Test
public void map_square_to_set() {

    List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
    Function<Integer, Integer> square = (x) -> x * x;

    Set<Integer> squaresList = myList.stream().map(square)
            .collect(Collectors.toSet());

    squaresList.forEach(System.out::println);
}

Output

16
1
4
9
25

Map one object to another

If you are looking for a way to convert from object A to object B java 8 makes it easy. Below we will show how to convert a list to map by first creating a POJO named JavaScriptFrameworks. Next initializing a List with three objects we will use a stream() to call the Collectors.toMap. The first parameter will accept a function that will generate the key while second parameter will generate the value. Finally we will loop over the elements using the for each

class JavaScriptFrameworks {
    
    private Integer rank;
    private String description;
    
    public JavaScriptFrameworks(Integer rank, String description) {
        super();
        this.rank = rank;
        this.description = description;
    }
}

@Test
public void objectAObjectB() {

    List<JavaScriptFrameworks> framework = new ArrayList<JavaScriptFrameworks>();
    framework.add(new JavaScriptFrameworks(1, "Angular"));
    framework.add(new JavaScriptFrameworks(2, "React"));
    framework.add(new JavaScriptFrameworks(3, "EmberJs"));

    Map<Integer, JavaScriptFrameworks> mappedFramework = framework.stream()
            .collect(
                    Collectors.toMap(JavaScriptFrameworks::getRank,
                            (p) -> p));

    mappedFramework.forEach((k, v) -> System.out.println("rank = " + k
            - " value = " + v));

}

Output

rank = 1 value = JavaScriptFrameworks [rank=1, description=Angular]
rank = 2 value = JavaScriptFrameworks [rank=2, description=React]
rank = 3 value = JavaScriptFrameworks [rank=3, description=EmberJs]

Java 8 primitive streams

If you are working within your favorite ide, you will notice three other map methods exists. mapToInt, mapToDouble, and mapToLong are methods designed to return primitive data streams. This is helpful if you are looking to perform a reduce operations on a stream.

Building on the squares snippet above passing in square function to map will produce a stream of Integers. Then calling mapToInt will return an IntStream where we can call max to return the maximum value in stream.

@Test
public void mapto() {

    List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);
    Function<Integer, Integer> square = (x) -> x * x;

    IntStream squaresIntStream = myList.stream().map(square)
            .mapToInt(Integer::intValue);

    System.out.println(squaresIntStream.max().getAsInt());;
}

Output

25

Mapping values using guava

Before java 8, you were left with transforming values in java using a imperative programming technique unless you were using a library such as guava. If you are familiar with the library, the code below will provide an example for reference.

@Test
public void map_square_guava() {

    List<Integer> myList = Arrays.asList(1, 2, 3, 4, 5);

    //com.google.common.base.Function
    Function<Integer, Integer> square = new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer value) {
            return value * value;
        }
    };

    List<Integer> squaresList = FluentIterable.from(myList)
            .transform(square).toList();

    System.out.println(squaresList);
}

Output

[1, 4, 9, 16, 25]

Converting from object to object or primitive streams, this tutorial scratched the surface in showing basic ways to use Stream.map function. Thanks for joining in today's levelup, have a great day!