java stream operations part 1 devmedium

Java Stream Operations – Part 1

8 min read

In the previous post, we went through basics of Stream API. We learnt how it works, what are its characteristics, flow of data within stream operations etc. In this post we will be learning Stream operations in depth. We will be explaining each operation with a practical example with code.

For all the coding examples that are going to be demonstrated, we will be using these classes for seeding data.

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class Employee {
    private String name;
    private String department;
    private String designation;
    private int salaryPerAnnum;
    private List<String> activities;
}
public class EmployeDatabase {

    public static List<Employee> getEmployees() {
        List<Employee> listOfEmployee = new ArrayList<>();
        Employee first = Employee.builder()
                .department("IT")
                .designation("Manager")
                .name("Paulo")
                .salaryPerAnnum(11)
                .activities(Arrays.asList("review, manage, scrum call"))
                .build();
        listOfEmployee.add(first);

        Employee second = Employee.builder()
                .department("IT")
                .designation("Tech Lead")
                .name("Peter")
                .salaryPerAnnum(10)
                .activities(Arrays.asList("review, code, scrum call, best practices, architecture"))
                .build();
        listOfEmployee.add(second);

        Employee third = Employee.builder()
                .department("Admin")
                .designation("Administrator")
                .name("Emma")
                .salaryPerAnnum(8)
                .activities(Arrays.asList("review, scrum call, networking, admin"))
                .build();
        listOfEmployee.add(third);

        Employee fourth = Employee.builder()
                .department("HR")
                .designation("Manager")
                .name("Zlatina")
                .salaryPerAnnum(10)
                .activities(Arrays.asList("recruitment, salary, hr"))
                .build();
        listOfEmployee.add(fourth);

        Employee fifth = Employee.builder()
                .department("IT")
                .designation("Developer")
                .name("Petra")
                .salaryPerAnnum(9)
                .activities(Arrays.asList("review, code, scrum call, best practices, architecture"))
                .build();
        listOfEmployee.add(fifth);

        Employee sixth = Employee.builder()
                .department("IT")
                .designation("Developer")
                .name("Rose")
                .salaryPerAnnum(6)
                .activities(Arrays.asList("review, code, scrum call, best practices, architecture"))
                .build();
        listOfEmployee.add(sixth);

        Employee seventh = Employee.builder()
                .department("IT")
                .designation("Devops")
                .name("Akshay")
                .salaryPerAnnum(7)
                .activities(Arrays.asList("review, code, scrum call, best practices, architecture"))
                .build();
        listOfEmployee.add(seventh);

        return listOfEmployee;
    }
}

Stream API- Map

Map is used to transform one type to another.

public class StreamMapExample {

    public static List<String> namesList(){
        List<String> employeNameList = EmployeDatabase.getEmployees().stream()
                .map(Employee::getName)  //method reference
                .map(String::toUpperCase)
                .collect(toList());
        return employeNameList;
    }

    public static void main(String[] args) {
        System.out.println(namesList());
    }
}
//[PAULO, PETER, EMMA, ZLATINA, PETRA, ROSE, AKSHAY]

In the above example, First we are creating stream from Collection returned from getEmployees() method. Then, we used map to transform Object of type Employee into Stream consisting of only names of employees. We again used map to get Stream of names transformed to uppercase. At the end, we used Collector terminal operation and returned List of employee names.

Stream API – Flatmap

Flatmap are used to transform a type to another type, wherein a type contains multiple elements. For ex, Stream<List>, Stream<Arrays> etc

public class StreamFlatMapExample {
    public static List<String> activityFlattenList(){
        List<String> employeActivityList = EmployeDatabase.getEmployees().stream()
                .map(Employee::getActivities)  //Stream<List<String>>
                .flatMap(List::stream)//Stream<String>
                .collect(toList());
        return employeActivityList;
    }

    public static void main(String[] args) {
        System.out.println(activityFlattenList());
    }
}
//[review, manage, scrum call, review, code, scrum call, best practices, architecture, review, scrum call, networking, admin, recruitment, salary, hr, review, code, scrum call, best practices, architecture, review, code, scrum call, best practices, architecture, review, code, scrum call, best practices, architecture]

In the above example, we wanted to retrieve all the activities as a List. Since activities itself is a List, therefore we cannot just use Map to get the activities. Hence to flatten the list to String we used flatmap and return list of activities.

Stream API – Distinct, Count and Sorted

Distinct: It will return stream of distinct elements.
Count: Returns a long with total number of elements in a stream.
Sorted: Sort the elements in a stream.

public class StreamFlatMapExample {
    public static List<String> activityFlattenList(){
        List<String> employeActivityList = EmployeDatabase.getEmployees().stream()
                .map(Employee::getActivities)  //Stream<List<String>>
                .flatMap(List::stream)//Stream<String>
                .distinct()//Stream of unique elements
                .collect(toList());
        return employeActivityList;
    }

    public static void main(String[] args) {
        System.out.println(activityFlattenList());
    }
}
//[review, manage, scrum call, review, code, scrum call, best practices, architecture, review, scrum call, networking, admin, recruitment, salary, hr]

In the above example, we have modified the previous code snippet for creating stream of unique activities after flattening list.

public class StreamFlatMapExample {
    public static Long activityFlattenList(){
        Long count = EmployeDatabase.getEmployees().stream()
                .map(Employee::getActivities)  //Stream<List<String>>
                .flatMap(List::stream)//Stream<String>
                .distinct()
                .count();
        return count;
    }

    public static void main(String[] args) {
        System.out.println(count));
    }
} //4

In the above example, we have used count as a terminal operation, that returns the number of elements in the incoming stream.

We will be continuing Stream operations in next post. Hope this post is helpful for your understanding. Keep reading!!

Happy Learning!!

Relevant Posts:

  1. Stream API Introduction
  2. Stream API Operations – Part 2
  3. Java Lambda Functional Interfaces
  4. Java Lambda Expressions- Basics