Understanding Java 8 Streams and working with collections using Lambda expressions
Assumes that you have read and understand Java 8 Lambda Expressions and functional interface tutorials
A stream is an infinite sequence of consumable elements (i.e a data structure) for the consumption of an operation or iteration. Any Collection can be exposed as a stream. The operations you perform on a stream can either be
- intermediate (map, filter, sorted, limit, skip,concat, substream, distinct, etc) producing another stream or
- terminal (forEach, reduce, collect, sum, max, count, matchAny, findFirst, findAny, etc) producing an object that is not a stream.
ls -l | grep "Dec" | Sort +4n | more
stream( ) is a default method added to the Collection interface in Java 8. The stream( ) returns a java.util.Stream interface with multiple abstract methods like filter, map, sorted, collect, etc. DelegatingStream is implements these abstract methods.
Java 8 Example 1:
package com.java8.examples; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class EmployeeTest { private static List<Employee> employees = Arrays.asList( new Employee("Steve", BigDecimal.valueOf(35000), Employee.WorkType.PARTTIME), new Employee("Peter", BigDecimal.valueOf(65000), Employee.WorkType.FULLTIME), new Employee("Sam", BigDecimal.valueOf(75000), Employee.WorkType.FULLTIME), new Employee("John", BigDecimal.valueOf(25000), Employee.WorkType.CASUAL)); public static void main(String[] args) { //e is the parameter for Employee List<Employee> fullTimeEmployees = employees.stream() //returns a stream (intermediate) .filter(e -> e.getWorkType() == Employee.WorkType.FULLTIME)//returns a stream (intermediate) .collect(Collectors.toList()); // returns a list (terminal) fullTimeEmployees.forEach(e -> System.out.println(e)); //Peter & Sam } }
The output is:
Employee [name=Peter, salary=65000, workType=FULLTIME]
Employee [name=Sam, salary=75000, workType=FULLTIME]
The above example creates a new list of full time employees. The operations .stream( ), .filter( ) create the intermediate streams, hence they are chained, and the .collect is the terminal operation that returns the final List of full-time employees.
This is enabled in the Iterable interface, which is a functional interface with the forEach default method. A List and other collections implements the Iterable functional interface to allow lambda expressions.
The Employee class will look like
package com.java8.examples; import java.math.BigDecimal; public class Employee { public enum WorkType {FULLTIME, PARTTIME, CASUAL} private String name; private BigDecimal salary; private WorkType workType; public Employee(String name, BigDecimal salary, WorkType workType) { super(); this.name = name; this.salary = salary; this.workType = workType; } public String getName() { return name; } public void setName(String name) { this.name = name; } public BigDecimal getSalary() { return salary; } public void setSalary(BigDecimal salary) { this.salary = salary; } public WorkType getWorkType() { return workType; } public void setWorkType(WorkType workType) { this.workType = workType; } @Override public String toString() { return "Employee [name=" + name + ", salary=" + salary + ", workType=" + workType + "]"; } }
Java 8 Example 2:
Now, in the same example, if you want to print all the employees who earn more than 25,000, sorted by WorkType, in the format "<name> earns <salary> on a <work type> basis.
//e is the parameter for Employee employees.stream() //returns a stream (intermediate) .filter(e -> e.getSalary().doubleValue() > 25000) // returns a stream (intermediate) .sorted((e1,e2) -> e1.getWorkType().compareTo(e2.getWorkType())) .map(e -> e.getName() + " earns " + e.getSalary() + " on a " + e.getWorkType() + " basis") .forEach(System.out::println); //terminal
Isn't this cool? This is like writing the SQL where clause.
Output:
Peter earns 65000 on a FULLTIME basis
Sam earns 75000 on a FULLTIME basis
Steve earns 35000 on a PARTTIME basis
Java 8 Example 3:
Get a comma separated string of all employees earning more than 25,000.00 as salary.
//e is the parameter for Employee String str = employees.stream() //returns a stream (intermediate) .filter(e -> e.getSalary().doubleValue() > 25000) // returns a stream (intermediate) .map(e -> e.getName())// returns a stream (intermediate) .distinct() //returns a stream (intermediate) //terminal returning a string .reduce("Distinct first names earning > 25000:", (name1, name2) -> name1+ "," + name2 ); System.out.println("CSV: " + str);
Output:
CSV: Distinct first names earning > 25000:,Steve,Peter,Sam
Java 8 Example 4:
Aggregate the salary by WorkType.
//e is the parameter for Employee employees.stream() //returns a stream (intermediate) .collect(Collectors.groupingBy(Employee::getWorkType)) .forEach((gr,le) -> {System.out.println(" Aggregated Salary for " + gr + " is " + + le.stream().mapToDouble(e -> e.getSalary().doubleValue()).sum()); });
Output:
Aggregated Salary for CASUAL is 25000.0
Aggregated Salary for FULLTIME is 140000.0
Aggregated Salary for PARTTIME is 35000.0
Java 8 Example 5:
Get the employee who earns the highest salary.
//e is the parameter for Employee Employee maxSalaryEmployee = employees.stream() //returns a stream (intermediate) .max((e1, e2) -> (e1.getSalary().compareTo(e2.getSalary()))) .get(); System.out.println(maxSalaryEmployee);
Output:
Employee [name=Sam, salary=75000, workType=FULLTIME]
Labels: Java 8
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home