Chapter 4. Collection Operations with Lambda

4.1.  Develop code to extract data from an object by using the map() method

Applying a function to each element of a stream

Streams support the method map(), which takes a Function as argument. The function is applied to each element, mapping it into a new element (the word mapping is used because it has a meaning similar to transforming but with the nuance of "creating a new version of" rather than "modifying"). For example, in the following code you pass a method reference Employee::getName to the map(...) method to extract the names of the employees in the stream:

public class Employee {
    private String name;
    public Employee(String n) {
        name = n;
    }
    public String getName() {
        return name;
    }
}
					


Stream<Employee> emps = Stream.of(new Employee("Mikalai"), new Employee("Volha"));
Stream<String> names = emps.map(Employee::getName);
List<String> staff = names.collect(Collectors.toList());
System.out.println(staff);

					

Output:

[Mikalai, Volha]
					

Because the method Employee.getName() returns a String, the stream outputted by the map() method is of type Stream<String>.

For example, if you wanted to find out the length of the name of each employee, you could do this by chaining another map(...) as follows:


Stream<Employee> emps = Stream.of(new Employee("Mikalai"), new Employee("Volha"));
Stream<String> names = emps.map(Employee::getName);
Stream<Integer> lengths = names.map(n -> n.length());
List<Integer> list = lengths.collect(Collectors.toList());
System.out.println(list);

					

Output:

[7, 5]
					

Primitive stream specializations

Java 8 introduces three primitive specialized stream interfaces that support specialized methods (like max(), sum(), average()) to work with streams of numbers: IntStream, DoubleStream, and LongStream, that respectively specialize the elements of a stream to be int primitives, double primitives, and long primitives - and thereby avoid hidden boxing costs.

[Warning]

The Stream interface has max(...) and min(...) methods, but they are not with empty parameter list as in IntStream, DoubleStream, LongStream and require a Comparator interface passed in as a parameter:

The Stream interface does not have average() and sum() methods.

Each of these three interfaces brings new methods to perform common numeric reductions such as sum() to calculate the sum of a numeric stream and max() to find the maximum element. In addition, they have methods to convert back to a stream of Objects when necessary.

Mapping to a numeric stream

The most common methods you will use to convert a stream to a primitive specialized version are Stream.mapToInt(), Stream.mapToDouble(), and Stream.mapToLong(). These methods work exactly like the method Stream.map() that you saw earlier but return a specialized stream instead of a Stream<T>. For example, you can use mapToInt() as follows to calculate the longest name of the employees:


Stream<Employee> emps = Stream.of(new Employee("Mikalai"), new Employee("Volha"), new Employee("Ivan"));
Stream<String> names = emps.map(e -> e.getName());
IntStream lengths = names.mapToInt(n -> n.length());
int i = lengths.max().getAsInt();
System.out.println(i);

					

Here, the method mapToInt() extracts all the lenghts from each name (represented as an int) and returns an IntStream as the result (rather than a Stream<Integer>). You can then call the max() method defined on the IntStream interface to calculate the longest name. IntStream also supports other convenience methods such as sum(), min(), and average().

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz