Unlocking Efficiency: Exploring Java 8 Stream API for Employee Data Operations

Unlocking Efficiency: Exploring Java 8 Stream API for Employee Data Operations

Today, let's delve into some commonly asked questions about the Java 8 Stream API. Java 8 introduced significant enhancements to the Collections framework with the Stream API, which allows for more concise and expressive code when dealing with collections. Below, we'll explore various operations that can be performed on an Employee class using Java 8 Streams.

Creating an Employee Class:

class Employee {

private int id;

private String name;

private int age;

private long salary;

private String gender;

private String deptName;

private String city;

private int yearOfJoining;

public Employee(int id, String name, int age, long salary, String gender,

String deptName, String city, int yearOfJoining) {

this.id = id;

this.name = name;

this.age = age;

this.salary = salary;

this.gender = gender;

this.deptName = deptName;

this.city = city;

this.yearOfJoining = yearOfJoining;

}

// Getters and setters omitted for brevity

@Override

public String toString() {

return "Employee{" +

"id=" + id +

", name='" + name + '\'' +

", age=" + age +

", salary=" + salary +

", gender='" + gender + '\'' +

", deptName='" + deptName + '\'' +

", city='" + city + '\'' +

", yearOfJoining='" + yearOfJoining + '\'' +

'}';

}

}

Creating a List of Employee Objects:

List<Employee> empList = new ArrayList<>();

empList.add(new Employee(1, "abc", 28, 123, "F", "HR", "Blore", 2020));

empList.add(new Employee(2, "xyz", 29, 120, "F", "HR", "Hyderabad", 2015));

empList.add(new Employee(3, "efg", 30, 115, "M", "HR", "Chennai", 2014));

empList.add(new Employee(4, "def", 32, 125, "F", "HR", "Chennai", 2013));

empList.add(new Employee(5, "ijk", 22, 150, "F", "IT", "Noida", 2013));

empList.add(new Employee(6, "mno", 27, 140, "M", "IT", "Gurugram", 2017));

empList.add(new Employee(7, "uvw", 26, 130, "F", "IT", "Pune", 2016));

empList.add(new Employee(8, "pqr", 23, 145, "M", "IT", "Trivandrum", 2015));

empList.add(new Employee(9, "stv", 25, 160, "M", "IT", "Blore", 2010));


Now, let's explore some common questions and operations that can be performed using Java 8 Streams on the empList:

Question 1: Grouping Employees by City

// Define a map to store employees grouped by city

Map<String, List<Employee>> empByCity;

// Group employees by city using Stream API

empByCity = empList.stream().collect(Collectors.groupingBy(Employee::getCity));

// Print the grouped employees

System.out.println("Employees grouped by city :: \n" + empByCity);

Explanation:

  • Stream Creation: We start by creating a stream from the list of employees (empList) using the stream() method.
  • GroupingBy Collector: The Collectors.groupingBy() collector is used to group the elements of the stream based on a classification function. In our case, we use Employee::getCity as the classification function, which extracts the city attribute from each employee object.
  • Collecting Results: The groupingBy collector returns a Map<String, List<Employee>>, where the keys represent distinct city names, and the values are lists of employees belonging to each city.
  • Printing Results: Finally, we print the grouped employees to the console for visualization using System.out.println().

Question 2: Grouping Employees by Age

// Define a map to store employees grouped by age

Map<Integer, List<Employee>> empByAge;

// Group employees by age using Stream API

empByAge = empList.stream().collect(Collectors.groupingBy(Employee::getAge));

// Print the grouped employees

System.out.println("Employees grouped by age :: \n" + empByAge);

Explanation:

  • Stream Creation: We start by creating a stream from the list of employees (empList) using the stream() method.
  • GroupingBy Collector: The Collectors.groupingBy() collector is used to group the elements of the stream based on a classification function. In this case, we use Employee::getAge as the classification function, which extracts the age attribute from each employee object.
  • Collecting Results: The groupingBy collector returns a Map<Integer, List<Employee>>, where the keys represent distinct ages, and the values are lists of employees belonging to each age group.
  • Printing Results: Finally, we print the grouped employees to the console for visualization using System.out.println().

Question 3: Finding the Count of Male and Female Employees

// Define a map to store the count of male and female employees

Map<String, Long> noOfMaleAndFemaleEmployees = empList.stream()

.collect(Collectors.groupingBy(Employee::getGender, Collectors.counting()));

// Print the count of male and female employees

System.out.println("Count of male and female employees present in the organization:: \n" + noOfMaleAndFemaleEmployees);


Explanation:

  • Stream Creation: We begin by creating a stream from the list of employees (empList) using the stream() method.
  • GroupingBy Collector: We utilize the Collectors.groupingBy() collector to group the elements of the stream based on a classification function. In this scenario, we use Employee::getGender as the classification function to group employees based on their gender.
  • Counting: Within the groupingBy collector, we also employ Collectors.counting() as a downstream collector. This downstream collector calculates the count of elements within each group.
  • Collecting Results: The groupingBy collector returns a Map<String, Long>, where the keys represent the distinct genders ('male' and 'female'), and the values represent the count of employees belonging to each gender.
  • Printing Results: Finally, we print the count of male and female employees present in the organization for visualization using System.out.println().

Question 4: Printing Names of All Departments

// Print the names of all departments in the organization

System.out.println("Names of all departments in the organization ");

empList.stream()

.map(Employee::getDeptName)

.distinct()

.forEach(System.out::println);

Explanation:

  • Stream Creation: We begin by creating a stream from the list of employees (empList) using the stream() method.
  • Mapping: With the map() operation, we transform each employee object into its corresponding department name using the Employee::getDeptName method reference.
  • Distinct Operation: We apply the distinct() operation to eliminate duplicate department names from the stream.
  • Terminal Operation (forEach): Finally, we use the forEach() terminal operation to iterate over each distinct department name in the stream and print it to the console using System.out::println.

Question 5: Printing Employee Details by Age Criteria

// Print employee details whose age is greater than 28

System.out.println("Employee details whose age is greater than 28");

empList.stream()

.filter(e -> e.getAge() > 28) // Filtering employees based on age criteria

.forEach(System.out::println); // Printing employee details

Explanation:

  • Stream Creation: We initiate a stream from the list of employees (empList) using the stream() method.
  • Filtering: With the filter() intermediate operation, we specify a predicate that checks if an employee's age is greater than 28. Only employees meeting this criterion will be included in the stream.
  • Terminal Operation (forEach): Utilizing the forEach() terminal operation, we iterate over each filtered employee in the stream and print their details to the console using System.out::println.

Question 6: Finding Maximum Age of Employee

// Find maximum age of employee

OptionalInt max = empList.stream()

.mapToInt(Employee::getAge) // Map employee ages to IntStream

.max(); // Find the maximum age

if (max.isPresent()) {

System.out.println("Maximum age of Employee: " + max.getAsInt());

}

Explanation:

  • Stream Creation: We begin by creating a stream of employee ages by using the mapToInt() method, which converts the Stream of Employees to an IntStream containing only the ages.
  • Finding Maximum Age: With the max() terminal operation, we find the maximum age among the employees in the IntStream.
  • Optional Handling: Since max() returns an OptionalInt, we use the isPresent() method to check if a maximum age exists. If it does, we retrieve the maximum age using getAsInt() and print it to the console.

Question 7: Printing Average Age of Male and Female Employees

// Print Average age of Male and Female Employees

Map<String, Double> avgAge = empList.stream()

.collect(Collectors.groupingBy(

Employee::getGender, // Group employees by gender

Collectors.averagingInt(Employee::getAge) // Compute average age for each gender

));

System.out.println("Average age of Male and Female Employees:: " + avgAge);

Explanation:

  • Stream Creation: We initiate a stream from the list of employees (empList) using the stream() method.
  • Grouping By Gender: Using the groupingBy() collector, we group employees by their gender. This creates a Map where the keys represent genders ("Male" and "Female"), and the values are lists of employees belonging to each gender.
  • Computing Average Age: Within the groupingBy() collector, we employ the averagingInt() downstream collector to compute the average age of employees for each gender group.
  • Printing Results: Finally, we print the resulting Map containing the average age of male and female employees to the console.

Question 8: Printing the Number of Employees in Each Department

// Print the number of employees in each department

Map<String, Long> countByDept = empList.stream()

.collect(Collectors.groupingBy(

Employee::getDeptName, // Group employees by department

Collectors.counting() // Count the number of employees in each department

));

System.out.println("Number of employees in each department:");

for (Map.Entry<String, Long> entry : countByDept.entrySet()) {

System.out.println(entry.getKey() + " : " + entry.getValue());

}

Explanation:

  • Stream Creation: We initiate a stream from the list of employees (empList) using the stream() method.
  • Grouping By Department: Using the groupingBy() collector, we group employees by their department names. This creates a Map where the keys represent department names, and the values are lists of employees belonging to each department.
  • Counting Employees: Within the groupingBy() collector, we employ the counting() downstream collector to count the number of employees in each department.
  • Printing Results: Finally, we iterate through the Map containing department names and their corresponding employee counts, printing them to the console.

Question 9: Finding the Oldest Employee

// Find the oldest employee

Optional<Employee> oldestEmp = empList.stream()

.max(Comparator.comparingInt(Employee::getAge));

// Retrieve the oldest employee details

if (oldestEmp.isPresent()) {

Employee oldestEmployee = oldestEmp.get();

System.out.println("Oldest employee details:: \n" + oldestEmployee);

} else {

System.out.println("No employees found in the list.");

}

Explanation:

  • Stream Creation: We initiate a stream from the list of employees (empList) using the stream() method.
  • Finding the Oldest Employee: Using the max() method along with Comparator.comparingInt(), we compare employees based on their age (getAge() method). This retrieves the employee with the highest age, i.e., the oldest employee.
  • Optional Handling: Since the max() method returns an Optional, we use the isPresent() method to check if an oldest employee exists in the stream.
  • Retrieving Employee Details: If an oldest employee is present, we retrieve the employee details using the get() method from the Optional and print them to the console.
  • Error Handling: In case the list of employees is empty, we handle this scenario by printing a message indicating that no employees were found in the list.

Question 10: Finding the Youngest Female Employee

// Find the youngest female employee

Optional<Employee> youngestEmp = empList.stream()

.filter(e -> e.getGender().equals("F")) // Filter by gender (female)

.min(Comparator.comparingInt(Employee::getAge)); // Find the minimum age

// Retrieve the youngest female employee details

if (youngestEmp.isPresent()) {

Employee youngestEmployee = youngestEmp.get();

System.out.println("Youngest Female employee details:: \n" + youngestEmployee);

} else {

System.out.println("No female employees found in the list.");

}

Explanation:

  • Stream Creation: We create a stream from the list of employees (empList) using the stream() method.
  • Filtering by Gender: Using the filter() method, we specify a predicate to include only female employees based on their gender attribute.
  • Finding the Minimum Age: With the min() method, we employ a comparator to determine the employee with the lowest age using Comparator.comparingInt().
  • Optional Handling: As min() returns an Optional, we use isPresent() to check if a youngest female employee exists in the stream.
  • Retrieving Employee Details: If a youngest female employee is present, we retrieve her details using get() from the Optional and print them to the console.
  • Error Handling: In case there are no female employees in the list, we handle this scenario by printing a message indicating that no female employees were found.

Question 11: Finding Employees by Age Range

// Find employees whose age is greater than 30 and less than 30

System.out.println("Employees whose age is greater than 25 and less than 25");

// Partition employees by age using Collectors.partitioningBy()

Map<Boolean, List<Employee>> partitionEmployeesByAge = empList.stream()

.collect(Collectors.partitioningBy(e -> e.getAge() > 30));

// Iterate through the partitioned map and print the results

Set<Map.Entry<Boolean, List<Employee>>> empSet = partitionEmployeesByAge.entrySet();

for (Map.Entry<Boolean, List<Employee>> entry : empSet) {

if (Boolean.TRUE.equals(entry.getKey())) {

// Employees greater than 30 years old

System.out.println("Employees greater than 30 years ::" + entry.getValue());

} else {

// Employees less than 30 years old

System.out.println("Employees less than 30 years ::" + entry.getValue());

}

}

Explanation:

  • Stream Creation: We create a stream from the list of employees (empList) using the stream() method.
  • Partitioning by Age: Using Collectors.partitioningBy(), we partition the employees based on the condition e.getAge() > 30. This results in a map where the keys represent whether the age is greater than 30 or not, and the values are lists of employees corresponding to each key.
  • Iterating Through the Map: We iterate through the partitioned map using a for-each loop over the entry set (empSet).
  • Printing Results: For each entry in the map, we check if the key is true (representing employees older than 30) or false (representing employees 30 or younger). We then print the corresponding list of employees.

Question 12: Finding Department with Highest Number of Employees

// Find the department name with the highest number of employees

Map.Entry<String, Long> maxNoOfEmployeesInDept = empList.stream()

.collect(Collectors.groupingBy(Employee::getDeptName, Collectors.counting()))

.entrySet().stream()

.max(Map.Entry.comparingByValue())

.get();

// Print the department with the highest number of employees

System.out.println("Max no of employees present in Dept :: " + maxNoOfEmployeesInDept.getKey());

Explanation:

  • Grouping by Department: We use Collectors.groupingBy() to group the employees by their department names (Employee::getDeptName). This operation results in a map where the keys are department names and the values are lists of employees belonging to each department.
  • Counting Employees per Department: Within the groupingBy() collector, we specify Collectors.counting() to count the number of employees in each department.
  • Finding the Entry with the Maximum Value: We obtain the entry with the maximum value (i.e., the department with the highest number of employees) using entrySet().stream().max(). The comparingByValue() method is used to compare the values of the map entries.
  • Retrieving the Department Name: Once we find the entry with the maximum value, we retrieve the key, which represents the department name with the highest number of employees.

Question 13: Finding Employees from HR Department

// Find if there are any employees from the HR Department

Optional<Employee> emp = empList.stream()

.filter(e -> e.getDeptName().equalsIgnoreCase("HR"))

.findAny();

// Check if an employee from the HR department is found

emp.ifPresent(employee -> System.out.println("Found employees from HR department: " + employee));

Explanation:

  • Filtering by Department: We use the filter() method to select employees whose department name (e.getDeptName()) matches "HR". This operation creates a stream containing only the employees from the HR department.
  • Finding Any Employee: We then call findAny() to retrieve an arbitrary employee from the HR department. The findAny() method returns an Optional<Employee> object, which may or may not contain an employee.
  • Checking and Printing the Result: We use the ifPresent() method to check if an employee from the HR department is found. If an employee is present, we print a message indicating that employees from the HR department are found.

Question 14: Finding Departments with Over 3 Employees

System.out.println("Department names where the number of employees in the department is over 3 :: ");

empList.stream()

.collect(Collectors.groupingBy(Employee::getDeptName, Collectors.counting()))

.entrySet().stream()

.filter(entry -> entry.getValue() > 3)

.forEach(System.out::println);

Explanation:

  • Grouping by Department Name and Counting Employees: The collect(Collectors.groupingBy(...)) method is used to group employees by their department names (Employee::getDeptName). We use Collectors.counting() to count the number of employees in each department.
  • Filtering by Number of Employees: After grouping, we obtain a map where the keys are department names, and the values represent the count of employees in each department. We then use the filter method to filter entries where the count of employees (entry.getValue()) is greater than 3.
  • Printing the Result: Finally, we use forEach(System.out::println) to print each department name where the number of employees exceeds 3.

Question 15: Finding Distinct Department Names

System.out.println("Distinct department names that employees work for:: ");

empList.stream()

.map(Employee::getDeptName) // Extract department names

.distinct() // Retrieve distinct department names

.forEach(System.out::println); // Print each distinct department name

Explanation:

  • Mapping Department Names: The map(Employee::getDeptName) operation extracts the department name from each employee object in the empList collection.
  • Finding Distinct Department Names: The distinct() method ensures that only unique department names are retained in the stream.
  • Printing Distinct Department Names: The forEach(System.out::println) method iterates over each distinct department name in the stream and prints it to the console.

Question 16: Finding and Sorting Employees by City

empList.stream() // Create a stream of employees

.filter(e -> e.getCity().equalsIgnoreCase("Blore")) // Filter employees living in 'Blore'

.sorted(Comparator.comparing(Employee::getName)) // Sort employees by name

.forEach(e -> System.out.println("Employees staying in Blore:: " + e.getName())); // Print the names of employees

Explanation:

  • Creating a Stream of Employees: The empList.stream() method creates a stream of Employee objects from the empList collection.
  • Filtering Employees by City: The filter() method is used to retain only those employees whose city is 'Blore'. The equalsIgnoreCase() method ensures case-insensitive comparison.
  • Sorting Employees by Name: The sorted() method sorts the filtered employees based on their names using the Comparator.comparing() method.
  • Printing Employee Names: The forEach() method iterates over each employee in the sorted stream and prints their names along with the message "Employees staying in Blore::".

Question 17: Counting the Number of Employees in the Organization

System.out.println("No of employees in the organisation :: " + empList.stream().count());

Explanation:

  • Creating a Stream of Employees: The empList.stream() method creates a stream of Employee objects from the empList collection.
  • Counting the Number of Employees: The count() method counts the total number of elements in the stream, which corresponds to the number of employees in the organization.
  • Printing the Count: The count value is concatenated with the message "No of employees in the organisation :: " and printed to the console using System.out.println().

Question 18: Finding Employee Count in Every Department

Map<String, Long> employeeCountInDepartmentMap = empList.stream().collect(Collectors.groupingBy(

Employee::getDeptName, Collectors.counting()));

System.out.print("Employee department and its count :- \n" + employeeCountInDepartmentMap);

Explanation:

  • Creating a Map of Department and Count: We utilize the collect method along with Collectors.groupingBy to group the employees by department. The groupingBy collector takes two parameters: the method reference Employee::getDeptName to extract the department name and Collectors.counting() to count the number of employees in each department.
  • Storing the Result: The result is stored in a Map<String, Long> where the keys are department names, and the values are the counts of employees in each department.
  • Printing the Result: We print the department names and their corresponding employee counts using System.out.print().

Question 19: Finding Department with the Highest Number of Employees

Optional<Map.Entry<String, Long>> deptNameWithHighestEmp = employeeCountInDepartmentMap.entrySet().stream()

.max(Map.Entry.comparingByValue());

if (deptNameWithHighestEmp.isPresent()) {

System.out.println("Department which has the highest number of employees " + deptNameWithHighestEmp.get());

}

Explanation:

  • Finding the Maximum Entry by Value: We use the max method on the stream of entries (Map.Entry<String, Long>) obtained from the employeeCountInDepartmentMap. The comparison is based on the value of each entry, i.e., the count of employees in each department.
  • Retrieving the Result as an Optional: The result of the max operation is stored in an Optional object, deptNameWithHighestEmp. This allows handling cases where the stream might be empty.
  • Checking and Printing the Result: We check if the Optional object contains a value using the isPresent() method. If a department with the highest number of employees is found, we print its name and count.

Question 20: Sorting Employees by Name and Age

System.out.println("Sorting based on name and age:: ");

// Comparator for sorting by name

Comparator<Employee> comparator1 = Comparator.comparing(Employee::getName);

// Comparator for sorting by age

Comparator<Employee> comparator2 = Comparator.comparingInt(Employee::getAge);

// Sorting the stream of employees using comparator chaining

empList.stream().sorted(comparator1.thenComparing(comparator2)).forEach(System.out::println);

Explanation:

  • Comparator for Name Sorting: We define a comparator comparator1 using the Comparator.comparing() method, which sorts employees based on their names. We use a method reference Employee::getName to extract the name field for comparison.
  • Comparator for Age Sorting: Similarly, we define another comparator comparator2 using Comparator.comparingInt(), which sorts employees based on their ages. We use a method reference Employee::getAge to extract the age field for comparison.
  • Comparator Chaining: To perform sorting based on multiple criteria, we use the thenComparing() method on the first comparator (comparator1). This method allows us to specify a secondary comparator (comparator2) to be applied when the values compared by the first comparator are equal.
  • Sorting the Stream: Finally, we call the sorted() method on the stream of employees (empList.stream()) and pass the composite comparator (comparator1.thenComparing(comparator2)) to perform the sorting operation.
  • Printing the Sorted Employees: We use the forEach() method to iterate over the sorted stream of employees and print each employee using the System.out::println method reference.

Question 21: Finding the Highest Experienced Employee

Optional<Employee> seniorEmp = empList.stream()

.sorted(Comparator.comparingInt(Employee::getYearOfJoining))

.findFirst();

System.out.println("Senior Employee Details: " + seniorEmp.get());

Explanation:

  • Sorting by Year of Joining: We start by streaming the list of employees (empList). Then, we use the sorted() method to sort the stream of employees based on the year they joined the organization. We employ a comparator generated by Comparator.comparingInt() to compare employees based on their yearOfJoining attribute.
  • Finding the First Employee: After sorting, we use the findFirst() method to retrieve the first employee in the sorted stream. Since the stream is sorted in ascending order of year of joining, the first employee in the stream will have the earliest year of joining, making them the most senior employee.
  • Printing Senior Employee Details: We retrieve the senior employee using the get() method on the Optional object seniorEmp and print their details using System.out.println().
  • Optional Handling: Note that seniorEmp is an Optional<Employee> to handle cases where the stream of employees might be empty. Using seniorEmp.get() directly without proper null-checking could result in a NoSuchElementException if the stream is empty. Ensure proper error handling based on your use case.

Question 22: Printing Average and Total Salary of the Organization

DoubleSummaryStatistics empSalary = empList.stream().collect(Collectors.summarizingDouble(Employee::getSalary));

System.out.println("Average Salary in the organisation = " + empSalary.getAverage());

System.out.println("Total Salary in the organisation = " + empSalary.getSum());

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Collecting Summary Statistics: We use the collect() method to perform a mutable reduction operation on the elements of the stream. We employ Collectors.summarizingDouble() to collect summary statistics, such as count, sum, min, average, and max, for the salaries of all employees.
  • Employee::getSalary: We pass a method reference to the getSalary() method of the Employee class. This method is invoked for each element in the stream to extract the salary value.
  • DoubleSummaryStatistics Object: The collect() method returns a DoubleSummaryStatistics object named empSalary, which contains various statistical measures like count, sum, min, average, and max for the salaries of all employees in the organization.
  • Printing Results: We use the getAverage() method of the DoubleSummaryStatistics object to retrieve the average salary, and the getSum() method to retrieve the total salary. We print these values to the console.

Question 23: Printing Average Salary of Each Department

System.out.println("Print Average salary of each department");

Map<String, Double> avgSalary = empList.stream().collect(Collectors.groupingBy(

Employee::getDeptName,

Collectors.averagingDouble(Employee::getSalary)));

Set<Map.Entry<String, Double>> entrySet = avgSalary.entrySet();

for (Map.Entry<String, Double> entry : entrySet) {

System.out.println(entry.getKey() + " : " + entry.getValue());

}

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Department: We use the Collectors.groupingBy() collector to group the employees by their department names. We pass a classifier function Employee::getDeptName to specify the grouping criterion.
  • Calculating Average Salary: For each department group, we use the Collectors.averagingDouble() collector to calculate the average salary of employees within that department. This collector computes the arithmetic mean of the salaries for each group.
  • Collecting Results: The result is a Map<String, Double> where the keys represent department names, and the values represent the average salary for each department.
  • Printing Results: We iterate over the entry set of the avgSalary map. For each entry, we print the department name (entry.getKey()) followed by the corresponding average salary (entry.getValue()).

Question 24: Finding the Highest Salary in the Organization

Optional<Employee> empHighest = empList.stream()

.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())

.findFirst();

System.out.println("Highest Salary in the organization : " + empHighest.get().getSalary());

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Sorting by Salary: We use the sorted() method to sort the stream of employees based on their salary. We pass a comparator Comparator.comparingDouble(Employee::getSalary).reversed() to sort in descending order of salary.
  • Finding the First Employee: After sorting, we call findFirst() to retrieve the first employee in the sorted stream, which corresponds to the employee with the highest salary.
  • Printing the Result: We use the getSalary() method of the employee object obtained from the optional to retrieve the highest salary and print it.
  • Optional Handling: Since findFirst() returns an Optional, we use .get() to retrieve the employee with the highest salary. Ensure that the list empList is not empty to avoid NoSuchElementException.

Question 25: Finding the Second Highest Salary in the Organization

Optional<Employee> emp2 = empList.stream()

.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())

.skip(1)

.findFirst();

System.out.println("Second Highest Salary in the organisation : " + emp2.get().getSalary());

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Sorting by Salary: We use the sorted() method to sort the stream of employees based on their salary. The comparator Comparator.comparingDouble(Employee::getSalary).reversed() is used to sort in descending order of salary.
  • Skipping the First Employee: We skip the first element in the sorted stream using skip(1). This effectively skips the employee with the highest salary.
  • Finding the Second Employee: After skipping the first highest salary, we call findFirst() to retrieve the first employee in the remaining sorted stream, which corresponds to the employee with the second-highest salary.
  • Printing the Result: We use the getSalary() method of the employee object obtained from the optional to retrieve the second-highest salary and print it.
  • Optional Handling: Since findFirst() returns an Optional, we use .get() to retrieve the employee with the second-highest salary. Ensure that the list empList contains at least two elements to avoid NoSuchElementException.

Question 26: Finding the Nth Highest Salary in the Organization

int n = 10; // Represents the Nth highest salary to find

Optional<Employee> empNthHighest = empList.stream()

.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())

.skip(n - 1)

.findFirst();

System.out.println("Nth Highest Salary in the organisation : " + empNthHighest.get().getSalary());

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Sorting by Salary: The stream of employees is sorted based on their salary in descending order using the sorted() method with a comparator that compares employee salaries.
  • Skipping Elements: We skip the first n - 1 employees using skip(n - 1). This effectively skips the first n - 1 employees with the highest salaries.
  • Finding the Nth Employee: After skipping the first n - 1 highest salaries, we call findFirst() to retrieve the first employee in the remaining sorted stream, which corresponds to the employee with the Nth highest salary.
  • Printing the Result: We use the getSalary() method of the employee object obtained from the optional to retrieve the Nth highest salary and print it.
  • Optional Handling: Since findFirst() returns an Optional, we use .get() to retrieve the employee with the Nth highest salary. Ensure that the list empList contains at least n elements to avoid NoSuchElementException.

Question 27: Finding the Highest Paid Salary in the Organization Based on Gender

Map<String, Optional<Employee>> highestPaidMFEmployee = empList.stream()

.collect(Collectors.groupingBy(Employee::getGender,

Collectors.maxBy((t1, t2) -> (int) (t1.getSalary() - t2.getSalary()))));

System.out.println("Highest paid male and female employee : " + highestPaidMFEmployee);

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Gender: Using Collectors.groupingBy, we group the employees based on their gender. This creates a map where the keys are genders ("Male" or "Female") and the values are lists of employees belonging to each gender.
  • Finding Maximum Salary for Each Gender: For each gender group, we use Collectors.maxBy to find the employee with the highest salary. This collector returns an Optional<Employee> representing the employee with the highest salary in each gender group.
  • Result: The result is a Map<String, Optional<Employee>> where the keys are genders ("Male" or "Female"), and the values are Optional<Employee> objects representing the highest paid employee of each gender.
  • Printing the Result: We print the map containing the highest paid male and female employees.

Question 28: Finding the Lowest Paid Salary in the Organization Based on Gender

Map<String, Optional<Employee>> lowestPaidMFEmployee = empList.stream()

.collect(Collectors.groupingBy(Employee::getGender,

Collectors.minBy((t1, t2) -> (int) (t1.getSalary() - t2.getSalary()))));

System.out.println("Lowest paid male and female employee : " + lowestPaidMFEmployee);

Explanation:

  • Stream Pipeline: We begin by streaming the list of employees (empList).
  • Grouping by Gender: Using Collectors.groupingBy, we group the employees based on their gender. This creates a map where the keys are genders ("Male" or "Female") and the values are lists of employees belonging to each gender.
  • Finding Minimum Salary for Each Gender: For each gender group, we use Collectors.minBy to find the employee with the lowest salary. This collector returns an Optional<Employee> representing the employee with the lowest salary in each gender group.
  • Result: The result is a Map<String, Optional<Employee>> where the keys are genders ("Male" or "Female"), and the values are Optional<Employee> objects representing the lowest paid employee of each gender.
  • Printing the Result: We print the map containing the lowest paid male and female employees.

Question 29: Sorting Employees' Salary in Ascending Order

System.out.println("Sorting the organisation's employee salary in ascending order ");

empList.stream()

.sorted(Comparator.comparingLong(Employee::getSalary))

.toList()

.forEach(System.out::println);

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Sorting by Salary: Using the sorted method, we specify a comparator using Comparator.comparingLong(Employee::getSalary) to sort the employees based on their salaries in ascending order.
  • Converting to List: After sorting, we use toList() to collect the sorted elements into a list.
  • Printing the Sorted List: Finally, we iterate over each employee in the sorted list using forEach and print out their details using System.out::println.

Question 30: Sorting Employees' Salary in Descending Order:

System.out.println("Sorting the organisation's employee salary in descending order ");

empList.stream()

.sorted(Comparator.comparingLong(Employee::getSalary).reversed())

.toList()

.forEach(System.out::println);

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Sorting by Salary in Descending Order: We use the sorted method along with a comparator to sort the employees based on their salaries in descending order. The comparator Comparator.comparingLong(Employee::getSalary).reversed() sorts the employees by their salaries in reverse order.
  • Collecting to List: After sorting, we use toList() to collect the sorted elements into a list.
  • Printing the Sorted List: Finally, we iterate over each employee in the sorted list using forEach and print out their details using System.out::println.

Question 31: Finding the Highest Salary Based on Department:

System.out.println("Highest salary dept wise:: \n" + empList.stream()

.collect(Collectors.groupingBy(

Employee::getDeptName,

Collectors.collectingAndThen(

Collectors.toList(),

list -> list.stream().max(Comparator.comparingDouble(Employee::getSalary))

)

)));

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Department: We use the groupingBy collector to group the employees by their department names (Employee::getDeptName). This creates a map where the keys are department names and the values are lists of employees in each department.
  • Collecting the Maximum Salary: For each department, we use collectingAndThen to perform an additional operation after collecting the elements. We collect the employees into a list, and then we stream over this list. Within the stream, we find the employee with the maximum salary using max(Comparator.comparingDouble(Employee::getSalary)).
  • Output: The result is a map where each department name is mapped to an optional employee object representing the employee with the highest salary in that department.

Question 32: Printing the List of Employee's Second Highest Record Based on Department:

System.out.println("Highest second salary dept wise:: \n" + empList.stream()

.collect(Collectors.groupingBy(

Employee::getDeptName,

Collectors.collectingAndThen(

Collectors.toList(),

list -> list.stream()

.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())

.skip(1)

.findFirst()

)

)));

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Department: Using the groupingBy collector, we group the employees by their department names (Employee::getDeptName). This creates a map where the keys are department names and the values are lists of employees in each department.
  • Finding the Second Highest Salary: For each department, we use collectingAndThen to perform an additional operation after collecting the elements. We collect the employees into a list, and then we stream over this list. Within the stream, we sort the employees by salary in descending order using sorted(Comparator.comparingDouble(Employee::getSalary).reversed()). We skip the first element (which is the highest salary) using skip(1), and then we find the first element using findFirst(). This gives us the employee with the second-highest salary in the department.
  • Output: The result is a map where each department name is mapped to an optional employee object representing the employee with the second-highest salary in that department.

Question 33: Sorting the Employees' Salary in Each Department in Ascending Order:

System.out.println("Sorting the department wise employee salary in ascending order:: ");

Map<String, Stream<Employee>> sortedEmployeeAsc = empList.stream()

.collect(Collectors.groupingBy(

Employee::getDeptName,

Collectors.collectingAndThen(

Collectors.toList(),

list -> list.stream().sorted(Comparator.comparingDouble(Employee::getSalary))

)

));

sortedEmployeeAsc.forEach((deptName, employees) -> {

System.out.println(deptName);

System.out.println(employees.collect(Collectors.toList()));

});

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Department: Using the groupingBy collector, we group the employees by their department names (Employee::getDeptName). This creates a map where the keys are department names and the values are lists of employees in each department.
  • Sorting Employees by Salary: For each department, we use collectingAndThen to perform an additional operation after collecting the elements. We collect the employees into a list, and then we stream over this list. Within the stream, we sort the employees by salary in ascending order using sorted(Comparator.comparingDouble(Employee::getSalary)).
  • Printing Sorted Lists: We iterate over the map entries using forEach. For each department, we print the department name followed by the sorted list of employees with their salaries in ascending order.

Question 34: Sorting the Employees' Salary in Each Department in Descending Order:

System.out.println("Sorting the department wise employee salary in descending order ");

Map<String, Stream<Employee>> sortedEmployeeDesc = empList.stream()

.collect(Collectors.groupingBy(

Employee::getDeptName,

Collectors.collectingAndThen(

Collectors.toList(),

list -> list.stream().sorted(Comparator.comparingDouble(Employee::getSalary).reversed())

)

));

sortedEmployeeDesc.forEach((deptName, employees) -> {

System.out.println(deptName);

System.out.println(employees.collect(Collectors.toList()));

});

Explanation:

  • Stream Pipeline: We start by streaming the list of employees (empList).
  • Grouping by Department: Using the groupingBy collector, we group the employees by their department names (Employee::getDeptName). This creates a map where the keys are department names and the values are lists of employees in each department.
  • Sorting Employees by Salary: For each department, we use collectingAndThen to perform an additional operation after collecting the elements. We collect the employees into a list, and then we stream over this list. Within the stream, we sort the employees by salary in descending order using sorted(Comparator.comparingDouble(Employee::getSalary).reversed()).
  • Printing Sorted Lists: We iterate over the map entries using forEach. For each department, we print the department name followed by the sorted list of employees with their salaries in descending order.

In conclusion, the article underscores the potency of Java streams and collectors for developers and aspiring developers, offering a versatile framework for effectively managing and analyzing data within diverse applications. By delving into the intricacies of Java streams and collectors, individuals can uncover insights across varied datasets, facilitating informed decision-making and streamlined operations across multiple domains.

Moreover, understanding Java streams and collectors is highly beneficial for job interviews in the software development field. Proficiency in these concepts demonstrates a candidate's ability to work with complex data structures and algorithms efficiently. Interviewers often seek candidates who can demonstrate practical knowledge of data manipulation and analysis, making Java streams and collectors a valuable skill set to showcase during technical discussions. Mastering these concepts not only enhances one's problem-solving skills but also reflects a deeper understanding of Java programming principles, thereby increasing one's competitiveness in the job market.


回复
Ramana Kumar Emani

Senior Java Developer/Technical Lead at Tata Consultancy Services Limited

10 个月

??

回复

Mastering Java Streams and Collectors is the key to unlocking efficient data operations! ??

要查看或添加评论,请登录

Gurunath Kadam的更多文章

社区洞察

其他会员也浏览了