Java 8 Stream.map()
operation transforms the elements of a stream from one type to another. After the map() operation completes, for each element of type X
in the current Stream, a new object of type Y
is created and put in the new Stream.
Stream<ElementType> —> map() operation —> Stream<NewElementType>
1. When do we use Stream.map() Operation?
The map() operation is particularly useful for data manipulation and transformation tasks. Consider a few possible usecases to understand when map() can be applied:
- During database migration, we may want to transform data from the old schema to the new schema. Using map(), we can define the field mappings between entities to copy their values.
- Data cleansing can be done with map() when we read data from different sources and convert it to a standard format before processing it in a standard way.
- In the MVC pattern, we can use map() to copy JPA entity data into VO objects for rendering the user views.
In the following example, we are using the map() to convert from Stream<PersonEntity> to Stream<PersonVO>
// Converting from Stream<PersonEntity> to Stream<PersonVO> and collecting into a new List
List<PersonEntity> personEntityList = ...; // A List of PersonEntity objects
List<PersonVO> personVoList = personEntityList.stream()
.map(e -> createVoFromEntity(e))
.toList();
//The utility function called in the map operation
public static PersonVO createVoFromEntity(PersonEntity entity) { ... }
2. Stream map() Method
2.1. Method Syntax
The Stream map()
method has the following syntax.
<R> Stream<R> map(Function<? super T,? extends R> mapper)
R
represents the element type of the new stream.mapper
is a non-interfering, stateless function to apply to each element which produces a stream of new values.- The method returns a new stream of objects of type
R
.
2.2. Description
- The
map()
is an intermediate operation. It returns a newStream
as return value. - The
map()
operation takes aFunction
, which is called for each value in the input stream and produces one result value sent to the output stream. - The mapper function used for transformation is a stateless function (does not store the information of previously processed objects) and returns only a single value.
- The
map()
method is used when we want to convert a Stream ofX
to Stream ofY
. - The mapped stream is closed after its contents have been placed into the new output stream.
map()
operation does not flatten the stream asflatMap()
operation does.
3. Stream map() Examples
Let us see a few more examples to understand it even better.
Example 1: Converting a Stream of Strings to a Stream of Integers
In this example, we will convert a Stream<String>
to Stream<Integer>
. Here the mapper function Integer::valueOf()
takes one string from the Stream at a time, and converts the String
to an Integer
.
It then puts the Integer
into another stream which is then collected using Collectors.toList()
.
List<String> listOfStrings = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> listOfIntegers = listOfStrings.stream()
.map(Integer::valueOf)
.collect(Collectors.toList());
System.out.println(listOfIntegers);
Program output.
[1, 2, 3, 4, 5]
Example 2: Finding all distinct salaries among all employees
Java example to find all possible distinct salaries for a List
of employees.
List<Employee> employeesList = Arrays.asList(
new Employee(1, "Alex", 100),
new Employee(2, "Brian", 100),
new Employee(3, "Charles", 200),
new Employee(4, "David", 200),
new Employee(5, "Edward", 300),
new Employee(6, "Frank", 300)
);
List<Double> distinctSalaries = employeesList.stream()
.map( e -> e.getSalary() )
.distinct()
.collect(Collectors.toList());
System.out.println(distinctSalaries);
Program output.
[100.0, 200.0, 300.0]
4. Stream of Integers, Longs or Doubles [Special Case]
Stream interface has three more similar methods for numeric types and are often used to perform numerical calculations or conversions. These methods produce IntStream
, LongStream
and DoubleStream
respectively.
IntStream mapToInt(ToIntFunction<? super T> mapper)
LongStream mapToLong(ToLongFunction<? super T> mapper)
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)
The benefit of using these classes is that they provide convenient methods to process the stream elements and perform mathematical/aggregate operations without the overhead of boxing and unboxing.
In the following example, we have a list of exam scores represented as strings, and we want to calculate the average score:
List<String> scoresAsString = Arrays.asList("85", "92", "78", "90", "88");
double averageScore = scoresAsString.stream()
.mapToInt(Integer::parseInt) // Convert strings to integers using mapToInt()
.average() // Calculate the average of the integers
.orElse(0.0); // Use 0.0 if there are no scores
System.out.println("Average score: " + averageScore);
Drop me your questions related to Stream map() method in Java Stream API.
Happy Learning !!
Comments