Chapter: Java The Complete Reference - The Java Library - The Stream API

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Mapping - Java Stream API

Often it is useful to map the elements of one stream to another. For example, a stream that contains a database of name, telephone, and e-mail address information might map only the name and e-mail address portions to another stream.

Mapping

 

Often it is useful to map the elements of one stream to another. For example, a stream that contains a database of name, telephone, and e-mail address information might map only the name and e-mail address portions to another stream. As another example, you might want to apply some transformation to the elements in a stream. To do this, you could map the transformed elements to a new stream. Because mapping operations are quite common, the stream API provides built-in support for them. The most general mapping method is map( ). It is shown here:

 

<R> Stream<R> map(Function<? super T, ? extends R> mapFunc)

 

Here, R specifies the type of elements of the new stream; T is the type of elements of the invoking stream; and mapFunc is an instance of Function, which does the mapping. The map function must be stateless and non-interfering. Since a new stream is returned, map( ) is an intermediate method.

 

Function is a functional interface declared in java.util.function. It is declared as shown here:

 

Function<T, R>

 

As it relates to map( ), T is the element type and R is the result of the mapping. Function has the abstract method shown here:

 

R apply(T val)

 

Here, val is a reference to the object being mapped. The mapped result is returned. The following is a simple example of map( ). It provides a variation on the previous

example program. As before, the program computes the product of the square roots of the values in an ArrayList. In this version, however, the square roots of the elements are first mapped to a new stream. Then, reduce( ) is employed to compute the product.

 

// Map one stream to another.

 

import java.util.*;

 

import java.util.stream.*;

 

class StreamDemo4 {

 

public static void main(String[] args) {

 

// A list of double values.

 

ArrayList<Double> myList = new ArrayList<>( );

 

myList.add(7.0);

 

myList.add(18.0);

 

myList.add(10.0);

 

myList.add(24.0);

 

myList.add(17.0);

 

myList.add(5.0);

 

// Map the square root of the elements in myList to a new stream.

Stream<Double> sqrtRootStrm = myList.stream().map((a) -> Math.sqrt(a));

// Find the product of the square roots.

 

double productOfSqrRoots = sqrtRootStrm.reduce(1.0, (a,b) -> a*b);

 

System.out.println("Product of square roots is " + productOfSqrRoots);

 

}

 

}

 

The output is the same as before. The difference between this version and the previous is simply that the transformation (i.e., the computation of the square roots) occurs during mapping, rather than during the reduction. Because of this, it is possible to use the two-parameter form of reduce( ) to compute the product because it is no longer necessary to provide a separate combiner function.

 

Here is an example that uses map( ) to create a new stream that contains only selected fields from the original stream. In this case, the original stream contains objects of type NamePhoneEmail, which contains names, phone numbers, and e-mail addresses. The program then maps only the names and phone numbers to a new stream of NamePhone objects. The e-mail addresses are discarded.

 

 

    //Use map() to create a new stream that contains only

 

    //selected aspects of the original stream.

 

import java.util.*;

 

import java.util.stream.*;

 

class NamePhoneEmail { String name;

 

String phonenum; String email;

 

NamePhoneEmail(String n, String p, String e) { name = n;

 

phonenum = p; email = e;

 

}

 

}

class NamePhone { String name; String phonenum;

 

NamePhone(String n, String p) { name = n;

 

phonenum = p;

 

}

 

}

 

class StreamDemo5 {

public static void main(String[] args) {

// A list of names, phone numbers, and e-mail addresses.

 ArrayList<NamePhoneEmail> myList = new ArrayList<>( );

 

myList.add(new NamePhoneEmail("Larry", "555-5555", "Larry@HerbSchildt.com"));

 

myList.add(new NamePhoneEmail("James", "555-4444", "James@HerbSchildt.com"));

 

myList.add(new NamePhoneEmail("Mary", "555-3333", "Mary@HerbSchildt.com"));

 

System.out.println("Original values in myList: "); myList.stream().forEach( (a) -> {

 

System.out.println(a.name + " " + a.phonenum + " " + a.email); });

 

System.out.println();

 

// Map just the names and phone numbers to a new stream.

 Stream<NamePhone> nameAndPhone = myList.stream().map(

 

(a) -> new NamePhone(a.name,a.phonenum) );

 

System.out.println("List of names and phone numbers: "); nameAndPhone.forEach( (a) -> {

 

System.out.println(a.name + " " + a.phonenum); });

 

}

 

}

 

The output, shown here, verifies the mapping:

 

Original values in myList:

 

Larry 555-5555 Larry@HerbSchildt.com

 

James 555-4444 James@HerbSchildt.com

 

Mary 555-3333 Mary@HerbSchildt.com

 

List of names and phone numbers:

 

Larry 555-5555

 

James 555-4444

 

Mary 555-3333

 

Because you can pipeline more than one intermediate operation together, you can easily create very powerful actions. For example, the following statement uses filter( ) and then map( ) to produce a new stream that contains only the name and phone number of the elements with the name "James":

Stream<NamePhone> nameAndPhone = myList.stream().

 

filter((a) -> a.name.equals("James")). map((a) -> new NamePhone(a.name,a.phonenum));

This type of filter operation is very common when creating database-style queries. As you gain experience with the stream API, you will find that such chains of operations can be used to create very sophisticated queries, merges, and selections on a data stream.

 

In addition to the version just described, three other versions of map( ) are provided. They return a primitive stream, as shown here:

 

IntStream mapToInt(ToIntFunction<? super T> mapFunc) LongStream mapToLong(ToLongFunction<? super T> mapFunc) DoubleStream mapToDouble(ToDoubleFunction<? super T> mapFunc)

 

Each mapFunc must implement the abstract method defined by the specified interface, returning a value of the indicated type. For example, ToDoubleFunction specifies the applyAsDouble(T val ) method, which must return the value of its parameter as a double.

 

Here is an example that uses a primitive stream. It first creates an ArrayList of Double values. It then uses stream( ) followed by mapToInt( ) to create an IntStream that contains the ceiling of each value.

 

// Map a Stream to an IntStream.

 

import java.util.*;

 

import java.util.stream.*;

 

class StreamDemo6 {

 

public static void main(String[] args) {

 

// A list of double values.

 

ArrayList<Double> myList = new ArrayList<>( );

 

myList.add(1.1);

 

myList.add(3.6);

 

myList.add(9.2);

 

myList.add(4.7);

 

myList.add(12.1);

 

myList.add(5.0);

 

System.out.print("Original values in myList: "); myList.stream().forEach( (a) -> {

 

System.out.print(a + " "); });

 

System.out.println();

 

// Map the ceiling of the elements in myList to an IntStream.

IntStream cStrm = myList.stream().mapToInt((a) -> (int) Math.ceil(a));

 

System.out.print("The ceilings of the values in myList: "); cStrm.forEach( (a) -> {

 

System.out.print(a + " "); });

 

}

The output is shown here:

 

Original values in myList: 1.1 3.6 9.2 4.7 12.1 5.0

 

The ceilings of the values in myList: 2 4 10 5 13 5

 

The stream produced by mapToInt( ) contains the ceiling values of the original elements in myList.

 

Before leaving the topic of mapping, it is necessary to point out that the stream API also provides methods that support flat maps. These are flatMap( ), flatMapToInt( ), flatMapToLong( ), and flatMapToDouble( ). The flat map methods are designed to handle situations in which each element in the original stream is mapped to more than one element in the resulting stream.

 

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail


Copyright © 2018-2020 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.