Sunday, February 14, 2021

Java Streaming API | map operation on streams


Hello Friends, Welcome to JavaHotFix Blog. We Continuously add good valuable information about the Java Eco System including cloud, Big Data processing, Functional Programming, and a lot of others. Thank you for visiting our Blog, Hope you will learn and grow in the java echo system.


Introducton

Java's Stream interface has map method, which accept Function<T,R> functional lamda. This lamda accept one input and return one output back to the streams. map operation is used to convert your streams element from one type to another type, modify the same element in between the flowing the elements or extract particular element from the stream element and pass it further for processing. This are the high level use cases of map operations. 

Use Cases of the Mapping Operation

- Converting an element to another element
- Extracting only certain field from the streams for further processing
- Modifying the Stream elements while they are flowing through the streams

Syntax

  • <R> Stream<R> map(Function<? super T,? extends R> mapper)
    Returns a stream consisting of the results of applying the given function to the elements of this stream.

    This is an intermediate operation.

    Type Parameters:
    R - The element type of the new stream
    Parameters:
    mapper - a non-interferingstateless function to apply to each element
    Returns:
    the new stream

Example 

Let's start with a basic example and we can dig deeper to explain it in more detail. In the Below example,  We are fetching Car from database in the CarDBModel class's object. Since this is a DTO Layer object, we don't need to show all information on the View Layers of the project. Since we have created CarViewModel class. Let's see how we have used the map functionality to achieve this.


public class JavaStreamingApiFilteringExample {

    public static void main(String args[]) {

List<CarViewModel> carViewModel = fetchAllAvailableFromFromDatabase()
.stream()
.map(new Function<CarDbModel, CarViewModel>() {
// This is Long way of Writing code
// We have refactored this code with Lambda below this code block
// This code block helps to the new learner of the Lambda things in java
@Override
public CarViewModel apply(CarDbModel carDbModel) {
return new CarViewModel(carDbModel.getNumber(), carDbModel.getModel(), carDbModel.getAge());
}
})
.collect(Collectors.toList());


System.out.println(carViewModel);
}

public static List<CarDbModel> fetchAllAvailableFromFromDatabase() {
return Arrays.asList(
new CarDbModel("MH12 AB1234", 1, "Mercedes GLS 350d", "someAdminPeople", "CAR0011"),
new CarDbModel("IN32 AB1234", 2, "Audi q7", "someAdminPeople", "CAR0012"),
new CarDbModel("DL78 AB1234", 3, "Ferrari 488", "someAdminPeople", "CAR0013"),
new CarDbModel("NY99 AB1234", 4, "rolls royce phantom", "someAdminPeople", "CAR0014"),
new CarDbModel("CA76 AB1234", 5, "Ford GT", "someAdminPeople", "CAR0015"),
new CarDbModel("EN90 AB1234", 6, "Lamborghini", "someAdminPeople", "CAR0016"),
new CarDbModel("CA56 AB1234", 7, "Porsche 911 GT2 RS", "someAdminPeople", "CAR0017"),
new CarDbModel("US34 AB1234", 8, "Nissan GT-R", "someAdminPeople", "CAR0018"),
new CarDbModel("MX11 AB1234", 9, "Aston Martin DBS", "someAdminPeople", "CAR0019"),
new CarDbModel("EU65 AB1234", 10, "Range Rover", "someAdminPeople", "CAR0020"));
}
}

class CarViewModel {
private String number;
private String model;
private int age;

public CarViewModel(String number, String model, int age) {
this.number = number;
this.model = model;
this.age = age;
}

@Override
public String toString() {
return "CarViewModel{" +
"number='" + number + '\'' +
", model='" + model + '\'' +
", age=" + age +
'}';
}
}

class CarDbModel {
private String number;
private int age;
private String model;
private String createdBy;
private String primaryKey;

public CarDbModel(String number, int age, String model, String createdBy, String primaryKey) {
this.number = number;
this.age = age;
this.model = model;
this.createdBy = createdBy;
this.primaryKey = primaryKey;
}

public String getNumber() {
return number;
}

public String getModel() {
return model;
}

public int getAge() {
return age;
}

@Override
public String toString() {
return "Car{" +
"number='" + number + '\'' +
", age=" + age +
", model='" + model + '\'' +
'}';
}
}

 

Refactored Code for Above Class Using Lamda & Lombok


The Above block of coding was not refactored since learning will be easy if we don't have lot of complex code. But at the end we should always make sure your code is clean and readble and follows Solid Principles. Here is little bit Refactored Version of the same code


public class JavaStreamingApiFilteringExample {
public static void main(String args[]) {

List<CarViewModel> carViewModel = fetchAllAvailableFromFromDatabase()
.stream()
// .map(CarDbModel::toCarViewModel) more cleaner code, since ownership of conversion lies with DTO and not this main method
.map(car -> new CarViewModel(carDbModel.getNumber(), carDbModel.getModel(), carDbModel.getAge()))
.collect(Collectors.toList());


System.out.println(carViewModel);
}

public static List<CarDbModel> fetchAllAvailableFromFromDatabase() {
return Arrays.asList(
new CarDbModel("MH12 AB1234", 1, "Mercedes GLS 350d", "someAdminPeople", "CAR0011"),
new CarDbModel("IN32 AB1234", 2, "Audi q7", "someAdminPeople", "CAR0012"),
new CarDbModel("DL78 AB1234", 3, "Ferrari 488", "someAdminPeople", "CAR0013"),
new CarDbModel("NY99 AB1234", 4, "rolls royce phantom", "someAdminPeople", "CAR0014"),
new CarDbModel("CA76 AB1234", 5, "Ford GT", "someAdminPeople", "CAR0015"),
new CarDbModel("EN90 AB1234", 6, "Lamborghini", "someAdminPeople", "CAR0016"),
new CarDbModel("CA56 AB1234", 7, "Porsche 911 GT2 RS", "someAdminPeople", "CAR0017"),
new CarDbModel("US34 AB1234", 8, "Nissan GT-R", "someAdminPeople", "CAR0018"),
new CarDbModel("MX11 AB1234", 9, "Aston Martin DBS", "someAdminPeople", "CAR0019"),
new CarDbModel("EU65 AB1234", 10, "Range Rover", "someAdminPeople", "CAR0020"));
}
}

@AllArgsConstructor @ToString @Getter
class CarViewModel {
private String number;
private String model;
private int age;
}

@AllArgsConstructor @ToString @Getter
class CarDbModel {
private String number;
private int age;
private String model;
private String createdBy;
private String primaryKey;

// owing up responsibility of creating different re-presentation of this object
public CarViewModel toCarViewModel() {
return new CarViewModel(this.getNumber(), this.getModel(), this.getAge());
}
}

References


That's all for this tutorial friends. Please let me know your comments, questions, or suggestion in below comment box, I will definitely try to improve the content and resolve your queries.

Saturday, February 13, 2021

Java Streaming API | Filtering elements from the streams


So, Todays we are going to learn how to filter out the unwanted elements from the Streams of any collection. Let's get Started on It

 

Let's start with a basic example and we can dig deeper to explain it in more detail. In the Below example, I would like to remove all old cars who manufactured 5 years before.

Detailed Version Code

public class JavaStreamingApiFilteringExample {
public static void main(String args[]) {

List<Car> listOfCars = Arrays.asList(
new Car("MH12 AB1234", 1, "Mercedes GLS 350d"),
new Car("IN32 AB1234", 2, "Audi q7"),
new Car("DL78 AB1234", 3, "Ferrari 488"),
new Car("NY99 AB1234", 4, "rolls royce phantom"),
new Car("CA76 AB1234", 5, "Ford GT"),
new Car("EN90 AB1234", 6, "Lamborghini"),
new Car("CA56 AB1234", 7, "Porsche 911 GT2 RS"),
new Car("US34 AB1234", 8, "Nissan GT-R"),
new Car("MX11 AB1234", 9, "Aston Martin DBS"),
new Car("EU65 AB1234", 10, "Range Rover"));

List<Car> carWithAgeLessThan5Years = listOfCars
.stream()
.filter(new Predicate<Car>() { // Long ways of Writing code, See improved version below with lambda functiona
@Override
public boolean test(Car car) {
// Since we need car with less than 5 year old. every other cars
// which will not satisfy this condition will get filtered out
return car.getAge() < 5;
}
})
.collect(Collectors.toList());

System.out.println(carWithAgeLessThan5Years);

}
}

class Car {
private String number;
private int age;
private String model;

// constructor, getter, setters and toString methods
}

 

Concise version code (Using lambda function)

public class JavaStreamingApiFilteringExample {
public static void main(String args[]) {

List<Car> listOfCars = Arrays.asList(
new Car("MH12 AB1234", 1, "Mercedes GLS 350d"),
new Car("IN32 AB1234", 2, "Audi q7"),
new Car("DL78 AB1234", 3, "Ferrari 488"),
new Car("NY99 AB1234", 4, "rolls royce phantom"),
new Car("CA76 AB1234", 5, "Ford GT"),
new Car("EN90 AB1234", 6, "Lamborghini"),
new Car("CA56 AB1234", 7, "Porsche 911 GT2 RS"),
new Car("US34 AB1234", 8, "Nissan GT-R"),
new Car("MX11 AB1234", 9, "Aston Martin DBS"),
new Car("EU65 AB1234", 10, "Range Rover"));

List<Car> carWithAgeLessThan5Years = listOfCars
.stream()
.filter( c -> c.getAge() < 5)
.collect(Collectors.toList());

System.out.println(carWithAgeLessThan5Years);
}
}

 

What is Predicate Interface?

In Java 8Predicate is a functional interface, which accepts an argument and returns a boolean. Usually, it used to apply in a filter for a collection of objects.

 

References :

Java DOC for Predicate interaface