Java 8 Stream Samples for Reference
1: Generate
// Example 1:Generate 10 Even Numbers
Stream.iterate(0, input -> input + 2)
.limit(10)
.forEach(System.out::println);
// Example 2: Generate 10 Random Numbers
Stream.generate(new Random()::nextInt)
.limit(10)
.forEach(System.out::println);
// Example 3: Generate 100 Student Objects for Testing
public class Student {
private int id;
Student(int id) {
this.id = id;
}
}
List<Student> students = Stream
.iterate(new Student(1), student -> new Student(student.id + 1))
.limit(100)
.collect(Collectors.toList());
// Example 4: Generate 10 Random UUIDs
List<String> infiniteStreamOfRandomUUID = Stream.generate(UUID::randomUUID)
.limit(10)
.map(UUID::toString)
.collect(Collectors.toList());
2: Reduce
// Combine List of names to form a comma separated String
List<String> list = Arrays.asList("Vignesh", "Valli", "Sita Mahalakshmi");
list.stream().reduce((s1, s2) -> s1 + "," + s2)
.ifPresent(System.out::println);
Let’s consider the below list of Employees for all upcoming samples
public class Employee {
private int id;
private String name;
private String city;
private int salary;
private Set<String> departments;
public Employee(int id, String name, String city, int salary, Set<String> departments) {
this.id = id;
this.name = name;
this.city = city;
this.salary = salary;
this.departments = departments;
}
// Getters & Setters to be followed
}
Set<String> deptSet1 = new HashSet<>();
deptSet1.add("SALES");
Set<String> deptSet2 = new HashSet<>();
deptSet2.add("HR");
deptSet2.add("MANAGEMENT");
Set<String> deptSet3 = new HashSet<>();
deptSet3.add("ENGINEERING");
deptSet3.add("MANAGEMENT");
Employee e1 = new Employee(1, "Valli", "Chennai", 55000, deptSet1);
Employee e2 = new Employee(2, "Vicky", "Chennai", 10000, deptSet1);
Employee e3 = new Employee(3, "Sita", "Bengaluru", 25000, deptSet2);
Employee e4 = new Employee(4, "Kriti", "Tokyo", 23450, deptSet3);
Employee e5 = new Employee(5, "Mahalakshmi", "HongKong", 34000, deptSet3);
List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5);
3: Finding Sum from Stream
// Total salaries of all Employees
// Both of the below examples achieve same result
Integer totalSalaryOfAllEmployees1 = employees.stream()
.map(Employee::getSalary)
.reduce(0, (total, salary) -> total + salary);
Integer totalSalaryOfAllEmployees2 = employees.stream()
.map(Employee::getSalary)
.reduce(0, Integer::sum);
4. Filter
// Filter Employees belong to city Chennai
List<Employee> employeesFromChennai = employees.stream()
.filter(employee -> employee.getCity().equalsIgnoreCase("Chennai"))
.collect(Collectors.toList());
5. Filter with Count
// Count number of Employees belong to city Chennai
long countOfEmployeesFromChennai = employees.stream()
.filter(employee -> employee.getCity().equalsIgnoreCase("Chennai"))
.count();
6. Sort Elements in the Streams
// Sort Employees based on their Salary
// Both of the below examples achieve same result
List<Employee> employeesSortedBasedOnSalary1 = employees.stream()
.sorted((emp1, emp2) -> emp1.getSalary() - emp2.getSalary())
.collect(Collectors.toList());
List<Employee> employeesSortedBasedOnSalary2 = employees.stream()
.sorted(Comparator.comparingInt(Employee::getSalary))
.collect(Collectors.toList());
// Sort List of Integer
List<Integer> sortedNumbers = Stream.of(1, 10, 13, 15, 16, 11, 9, 2, 7, 34)
.sorted()
.collect(Collectors.toList());
7. Skip Few Items from Stream
// When you want to get everything after the given nth element
List<Employee> skipFirstTwoEmployees = employees.stream()
.skip(2)
.collect(Collectors.toList());
// When you want to get first n elements from a List
List<Employee> skipAnythingAfterFirstTwoEmployees = employees.stream()
.limit(2)
.collect(Collectors.toList());
8. Find Min & Max Elements from Stream
// Find Employee with Max salary
// Both of the below examples achieve same result
Optional<Employee> employeeWithMaxSalary1 = employees.stream()
.max((emp1, emp2) -> emp1.getSalary() - emp2.getSalary());
Optional<Employee> employeeWithMaxSalary2 = employees.stream()
.max(Comparator.comparingInt(Employee::getSalary));
// Find Employee with Min salary
// Both of the below examples achieve same result
Optional<Employee> employeeWithMinSalary1 = employees.stream()
.min((emp1, emp2) -> emp1.getSalary() - emp2.getSalary());
Optional<Employee> employeeWithMinSalary2 = employees.stream()
.min(Comparator.comparingInt(Employee::getSalary));
9. Just Do Something on the Stream without disturbing the Stream (PEEK)
// We are just printing Employee before collecting them again in a List
List<Employee> employeesList = employees.stream()
.peek(System.out::println)
.collect(Collectors.toList());
10. Stream to Array
Employee[] employeeArray = employees.stream().toArray(Employee[]::new);
11. Array to Stream
int[] array = {1, 10, 9, 2, 4, 11, 23};
List<Integer> collect = Arrays.stream(array)
.boxed() // boxed() will convert int to Integer
.collect(Collectors.toList());
12. FlatMap
// Each Employee belongs to Set of Departments. Here we collected all
// Department names in a Set
Set<String> addDepartmentNames = employees.stream()
.map(Employee::getDepartments)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
13. Check if Elements in Stream Matching Certain Condition
// Check if Salary of All Employees in the given list greater than 10k
boolean checkIfSalaryOfAllEmployeeGreaterThan = employees.stream()
.allMatch(employee -> employee.getSalary() > 10000);
// Check if Salary of any one of the Employees in given list greater than 10k
boolean checkIfAnyEmployeeSalaryGreaterThan = employees.stream()
.anyMatch(employee -> employee.getSalary() > 10000);
14. Find Elements from Stream Matching Certain Condition
// Both of the below examples achieve same result
// Find First Employee from the Stream whose Salary is greater than 10000
Optional<Employee> employeeWithSalaryGreaterThan = employees.stream()
.filter(employee -> employee.getSalary() > 10000)
.findAny();
// Find First Employee from the Stream whose Salary is greater than 10000
Optional<Employee> employeeWithSalaryGreaterThan = employees.stream()
.filter(employee -> employee.getSalary() > 10000)
.findFirst();
Note: findAny() & findFirst() will return same result if the stream is not running in parallel
If the stream in parallel, there is no guarantee which element findAny() may return
// Since Parallel Stream is used, random Employee matching given condition
// will be returned
// Find Random Employee from the Stream whose Salary is greater than 10000
Optional<Employee> randomEmployeeWithSalaryGreaterThan2 = employees.parallelStream()
.filter(employee -> employee.getSalary() > 10000)
.findAny();
15. Stream to Map
// Collect Employees by their ID
Map<Integer, Employee> employeeById = employees.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity()));
// Collect Employees by their ID & have them sorted based on the ID
TreeMap<Integer, Employee> employeeById = employees.stream()
.collect(Collectors.toMap(Employee::getId, Function.identity(),
(emp1, emp2) -> emp1, TreeMap::new));
Note: To use Collectors.toMap -> the key we choose (in above case, Employee::getId) should give unique result. If not, it will end up in below Exception
Exception in thread “main” java.lang.IllegalStateException: Duplicate key
If each key is going to result in multiple values, then we need to use Collectors.groupingBy
// Group Employees Based on their City
Map<String, List<Employee>> employeeGroupedByCity = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity));
// Group Employee Names Based on their City
Map<String, List<String>> employeeNameListGroupedByCity = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity,
Collectors.mapping(Employee::getName, Collectors.toList())));
// Count Employees Based on their City. Count will be in Long type
Map<String, Long> employeeCountBasedOnCity = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity, Collectors.counting()));
// Count Employees Based on their City. Count will be in Integer type
Map<String, Integer> employeeCountAsIntegerBasedOnCity = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity,
Collectors.collectingAndThen(Collectors.counting(), Long::intValue)));
// Group Employees based on City & Each Group should be further grouped by
// their ID
Map<String, Map<Integer, Employee>> groupEmployees = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity,
Collectors.toMap(Employee::getId, Function.identity())));
// Group Employees based on City & Each Group should be further grouped by
// their ID & Set of Departments they work on
Map<String, Map<Integer, Set<String>>> map2 = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity,
Collectors.toMap(Employee::getId, Employee::getDepartments)));
// Collect Highest Paid Employee by City
Map<String, Optional<Employee>> reduceByCityAvgGrade = employees.stream()
.collect(Collectors.groupingBy(Employee::getCity,
Collectors.reducing(BinaryOperator.maxBy(
Comparator.comparing(Employee::getSalary)))));
// Count based on the first character in String
Map<String, Integer> output = Stream.of("My", "Name", "Is", "Mr", "Vicky")
.collect(Collectors.groupingBy(x-> x.substring(0, 1),
Collectors.reducing(0, String::length, Integer::sum)));
Thats all folks !!!