Last active
September 7, 2025 08:24
-
-
Save carefree-ladka/5b90e515bd44122cc50d768a93278e86 to your computer and use it in GitHub Desktop.
Java Streams API (https://medium.com/@asishpanda444/stream-api-coding-qna-8df8682b7e2a)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.util.Arrays; | |
| import java.util.Comparator; | |
| import java.util.List; | |
| import java.util.Map; | |
| import java.util.Optional; | |
| import java.util.Set; | |
| import java.util.stream.Collectors; | |
| import java.util.stream.IntStream; | |
| import java.util.stream.Stream; | |
| record Employee( | |
| int id, | |
| String name, | |
| int age, | |
| String departNames, | |
| String address, | |
| double salary, | |
| String gender) { | |
| } | |
| class StreamOperationsExample { | |
| /** | |
| * Main method demonstrating comprehensive Stream API operations | |
| */ | |
| public static void main(String[] args) { | |
| List<Employee> employees = Arrays.asList( | |
| new Employee(1, "Aabraham", 29, "IT", "Mumbai", 20000, "Male"), | |
| new Employee(2, "Mary", 27, "Sales", "Chennai", 25000, "Female"), | |
| new Employee(3, "Joe", 28, "IT", "Chennai", 22000, "Male"), | |
| new Employee(4, "John", 29, "Sales", "Gurgaon", 29000, "Male"), | |
| new Employee(5, "Liza", 25, "Sales", "Bangalore", 32000, "Female"), | |
| new Employee(6, "Peter", 27, "Admin", "Mumbai", 31500, "Male"), | |
| new Employee(7, "Harry", 30, "Research", "Kochi", 21000, "Male"), | |
| new Employee(8, "Anna", 26, "IT", "Delhi", 35000, "Female"), | |
| new Employee(9, "Bob", 32, "Admin", "Delhi", 28000, "Male"), | |
| new Employee(10, "Carol", 24, "Research", "Mumbai", 19000, "Female")); | |
| System.out.println("=== FILTERING OPERATIONS ==="); | |
| filterOperations(employees); | |
| System.out.println("\n=== MAPPING OPERATIONS ==="); | |
| mappingOperations(employees); | |
| System.out.println("\n=== GROUPING OPERATIONS ==="); | |
| groupingOperations(employees); | |
| System.out.println("\n=== AGGREGATION OPERATIONS ==="); | |
| aggregationOperations(employees); | |
| System.out.println("\n=== SORTING OPERATIONS ==="); | |
| sortingOperations(employees); | |
| System.out.println("\n=== FINDING OPERATIONS ==="); | |
| findingOperations(employees); | |
| System.out.println("\n=== MATCHING OPERATIONS ==="); | |
| matchingOperations(employees); | |
| System.out.println("\n=== ADVANCED OPERATIONS ==="); | |
| advancedOperations(employees); | |
| System.out.println("\n=== COLLECTION OPERATIONS ==="); | |
| collectionOperations(employees); | |
| } | |
| /** | |
| * Demonstrates various filtering operations using Stream.filter() | |
| * Filters elements based on specified predicates | |
| */ | |
| private static void filterOperations(List<Employee> employees) { | |
| // Find employees whose name starts with 'A' | |
| List<Employee> nameStartsWithA = employees.stream() | |
| .filter(e -> e.name().toLowerCase().startsWith("a")) | |
| .collect(Collectors.toList()); | |
| System.out.println("Employees with names starting with 'A': " + nameStartsWithA.size()); | |
| // Find employees with age less than 30 | |
| List<Employee> youngEmployees = employees.stream() | |
| .filter(e -> e.age() < 30) | |
| .collect(Collectors.toList()); | |
| System.out.println("Employees under 30: " + youngEmployees.size()); | |
| // Find employees with age between 26 and 31 (inclusive) | |
| List<Employee> midAgeEmployees = employees.stream() | |
| .filter(e -> e.age() >= 26 && e.age() <= 31) | |
| .collect(Collectors.toList()); | |
| System.out.println("Employees aged 26-31: " + midAgeEmployees.size()); | |
| // Find employees from specific city | |
| List<Employee> mumbaiEmployees = employees.stream() | |
| .filter(e -> e.address().equals("Mumbai")) | |
| .collect(Collectors.toList()); | |
| System.out.println("Employees from Mumbai: " + mumbaiEmployees.size()); | |
| // Find high-earning employees (salary > 25000) | |
| List<Employee> highEarners = employees.stream() | |
| .filter(e -> e.salary() > 25000) | |
| .collect(Collectors.toList()); | |
| System.out.println("High earners (>25000): " + highEarners.size()); | |
| } | |
| /** | |
| * Demonstrates mapping operations using map(), mapToInt(), flatMap() | |
| * Transforms elements from one type to another | |
| */ | |
| private static void mappingOperations(List<Employee> employees) { | |
| // Extract all employee names | |
| List<String> names = employees.stream() | |
| .map(Employee::name) | |
| .collect(Collectors.toList()); | |
| System.out.println("All employee names: " + names); | |
| // Extract ages as IntStream for numerical operations | |
| int[] ages = employees.stream() | |
| .mapToInt(Employee::age) | |
| .toArray(); | |
| System.out.println("Ages array length: " + ages.length); | |
| // Convert salaries to formatted strings | |
| List<String> formattedSalaries = employees.stream() | |
| .map(e -> String.format("%s: $%.2f", e.name(), e.salary())) | |
| .collect(Collectors.toList()); | |
| System.out.println("Formatted salaries count: " + formattedSalaries.size()); | |
| // Map to uppercase department names | |
| List<String> upperCaseDepts = employees.stream() | |
| .map(e -> e.departNames().toUpperCase()) | |
| .distinct() | |
| .collect(Collectors.toList()); | |
| System.out.println("Uppercase departments: " + upperCaseDepts); | |
| // FlatMap example - split names into characters | |
| List<String> nameCharacters = employees.stream() | |
| .flatMap(e -> e.name().chars() | |
| .mapToObj(c -> String.valueOf((char) c))) | |
| .distinct() | |
| .collect(Collectors.toList()); | |
| System.out.println("Unique characters in all names: " + nameCharacters.size()); | |
| } | |
| /** | |
| * Demonstrates grouping operations using Collectors.groupingBy() | |
| * Groups elements based on specified classifiers | |
| */ | |
| private static void groupingOperations(List<Employee> employees) { | |
| // Group employees by department | |
| Map<String, List<Employee>> byDepartment = employees.stream() | |
| .collect(Collectors.groupingBy(Employee::departNames)); | |
| System.out.println("Departments: " + byDepartment.keySet()); | |
| // Group by gender with count | |
| Map<String, Long> genderCount = employees.stream() | |
| .collect(Collectors.groupingBy(Employee::gender, Collectors.counting())); | |
| System.out.println("Gender distribution: " + genderCount); | |
| // Group by age range | |
| Map<String, List<Employee>> ageGroups = employees.stream() | |
| .collect(Collectors.groupingBy(e -> { | |
| if (e.age() < 26) | |
| return "Young"; | |
| else if (e.age() < 30) | |
| return "Mid"; | |
| else | |
| return "Senior"; | |
| })); | |
| System.out.println("Age groups: " + ageGroups.keySet()); | |
| // Group by city with average salary | |
| Map<String, Double> avgSalaryByCity = employees.stream() | |
| .collect(Collectors.groupingBy( | |
| Employee::address, | |
| Collectors.averagingDouble(Employee::salary))); | |
| System.out.println("Average salary by city: " + avgSalaryByCity); | |
| // Multi-level grouping: department then gender | |
| Map<String, Map<String, List<Employee>>> deptGenderGroup = employees.stream() | |
| .collect(Collectors.groupingBy( | |
| Employee::departNames, | |
| Collectors.groupingBy(Employee::gender))); | |
| System.out.println("Department-Gender groups: " + deptGenderGroup.keySet()); | |
| } | |
| /** | |
| * Demonstrates aggregation operations like count, sum, average, min, max | |
| * Performs mathematical operations on stream elements | |
| */ | |
| private static void aggregationOperations(List<Employee> employees) { | |
| // Count total employees | |
| long totalCount = employees.stream().count(); | |
| System.out.println("Total employees: " + totalCount); | |
| // Sum of all salaries | |
| double totalSalary = employees.stream() | |
| .mapToDouble(Employee::salary) | |
| .sum(); | |
| System.out.println("Total salary: $" + totalSalary); | |
| // Average salary | |
| double averageSalary = employees.stream() | |
| .mapToDouble(Employee::salary) | |
| .average() | |
| .orElse(0.0); | |
| System.out.println("Average salary: $" + String.format("%.2f", averageSalary)); | |
| // Maximum age | |
| int maxAge = employees.stream() | |
| .mapToInt(Employee::age) | |
| .max() | |
| .orElse(0); | |
| System.out.println("Maximum age: " + maxAge); | |
| // Minimum salary | |
| double minSalary = employees.stream() | |
| .mapToDouble(Employee::salary) | |
| .min() | |
| .orElse(0.0); | |
| System.out.println("Minimum salary: $" + minSalary); | |
| // Statistics summary | |
| var salaryStats = employees.stream() | |
| .mapToDouble(Employee::salary) | |
| .summaryStatistics(); | |
| System.out.println("Salary statistics: " + salaryStats); | |
| } | |
| /** | |
| * Demonstrates sorting operations using sorted() with various comparators | |
| * Orders elements based on specified criteria | |
| */ | |
| private static void sortingOperations(List<Employee> employees) { | |
| // Sort by name alphabetically | |
| List<Employee> sortedByName = employees.stream() | |
| .sorted(Comparator.comparing(Employee::name)) | |
| .collect(Collectors.toList()); | |
| System.out.println("First employee by name: " + sortedByName.get(0).name()); | |
| // Sort by salary (descending) | |
| List<Employee> sortedBySalaryDesc = employees.stream() | |
| .sorted(Comparator.comparing(Employee::salary).reversed()) | |
| .collect(Collectors.toList()); | |
| System.out.println("Highest paid employee: " + sortedBySalaryDesc.get(0).name()); | |
| // Sort by age then by salary | |
| List<Employee> sortedByAgeThenSalary = employees.stream() | |
| .sorted(Comparator.comparing(Employee::age) | |
| .thenComparing(Employee::salary)) | |
| .collect(Collectors.toList()); | |
| System.out.println("First by age-salary: " + sortedByAgeThenSalary.get(0).name()); | |
| // Sort by department then by name | |
| List<Employee> sortedByDeptThenName = employees.stream() | |
| .sorted(Comparator.comparing(Employee::departNames) | |
| .thenComparing(Employee::name)) | |
| .collect(Collectors.toList()); | |
| System.out.println("First by dept-name: " + sortedByDeptThenName.get(0).name()); | |
| // Custom sorting - by name length | |
| List<Employee> sortedByNameLength = employees.stream() | |
| .sorted(Comparator.comparing(e -> e.name().length())) | |
| .collect(Collectors.toList()); | |
| System.out.println("Shortest name: " + sortedByNameLength.get(0).name()); | |
| } | |
| /** | |
| * Demonstrates finding operations like findFirst(), findAny(), and nth elements | |
| * Locates specific elements in the stream | |
| */ | |
| private static void findingOperations(List<Employee> employees) { | |
| // Find first employee | |
| Optional<Employee> firstEmployee = employees.stream().findFirst(); | |
| System.out.println("First employee: " + firstEmployee.map(Employee::name).orElse("None")); | |
| // Find any employee from IT department | |
| Optional<Employee> anyITEmployee = employees.stream() | |
| .filter(e -> e.departNames().equals("IT")) | |
| .findAny(); | |
| System.out.println("Any IT employee: " + anyITEmployee.map(Employee::name).orElse("None")); | |
| // Find employee with highest salary | |
| Optional<Employee> highestPaid = employees.stream() | |
| .max(Comparator.comparing(Employee::salary)); | |
| System.out.println("Highest paid: " + highestPaid.map(Employee::name).orElse("None")); | |
| // Find youngest employee | |
| Optional<Employee> youngest = employees.stream() | |
| .min(Comparator.comparing(Employee::age)); | |
| System.out.println("Youngest employee: " + youngest.map(Employee::name).orElse("None")); | |
| // Find second highest salary employee | |
| Optional<Employee> secondHighest = employees.stream() | |
| .sorted(Comparator.comparing(Employee::salary).reversed()) | |
| .skip(1) | |
| .findFirst(); | |
| System.out.println("Second highest paid: " + secondHighest.map(Employee::name).orElse("None")); | |
| // Find employee by specific criteria (exact match) | |
| Optional<Employee> specificEmployee = employees.stream() | |
| .filter(e -> e.name().equals("Mary") && e.departNames().equals("Sales")) | |
| .findFirst(); | |
| System.out.println("Specific employee found: " + specificEmployee.isPresent()); | |
| } | |
| /** | |
| * Demonstrates matching operations using anyMatch(), allMatch(), noneMatch() | |
| * Tests conditions against stream elements | |
| */ | |
| private static void matchingOperations(List<Employee> employees) { | |
| // Check if any employee is from Mumbai | |
| boolean anyFromMumbai = employees.stream() | |
| .anyMatch(e -> e.address().equals("Mumbai")); | |
| System.out.println("Any employee from Mumbai: " + anyFromMumbai); | |
| // Check if all employees are above 18 | |
| boolean allAdults = employees.stream() | |
| .allMatch(e -> e.age() >= 18); | |
| System.out.println("All employees are adults: " + allAdults); | |
| // Check if no employee has salary above 40000 | |
| boolean noneAbove40k = employees.stream() | |
| .noneMatch(e -> e.salary() > 40000); | |
| System.out.println("No employee earns above 40k: " + noneAbove40k); | |
| // Check if any female employee exists | |
| boolean anyFemale = employees.stream() | |
| .anyMatch(e -> e.gender().equals("Female")); | |
| System.out.println("Any female employee: " + anyFemale); | |
| // Check if all employees have valid salaries (> 0) | |
| boolean allValidSalaries = employees.stream() | |
| .allMatch(e -> e.salary() > 0); | |
| System.out.println("All have valid salaries: " + allValidSalaries); | |
| } | |
| /** | |
| * Demonstrates advanced Stream operations like distinct, limit, skip, peek | |
| * Performs specialized stream manipulations | |
| */ | |
| private static void advancedOperations(List<Employee> employees) { | |
| // Get distinct departments | |
| Set<String> distinctDepts = employees.stream() | |
| .map(Employee::departNames) | |
| .collect(Collectors.toSet()); | |
| System.out.println("Distinct departments: " + distinctDepts); | |
| // Get first 3 employees | |
| List<Employee> firstThree = employees.stream() | |
| .limit(3) | |
| .collect(Collectors.toList()); | |
| System.out.println("First 3 employees: " + firstThree.size()); | |
| // Skip first 2 and get next 3 | |
| List<Employee> skipAndTake = employees.stream() | |
| .skip(2) | |
| .limit(3) | |
| .collect(Collectors.toList()); | |
| System.out.println("Skip 2, take 3: " + skipAndTake.size()); | |
| // Using peek for debugging/side effects | |
| List<String> processedNames = employees.stream() | |
| .filter(e -> e.salary() > 25000) | |
| .peek(e -> System.out.println("Processing: " + e.name())) | |
| .map(Employee::name) | |
| .collect(Collectors.toList()); | |
| System.out.println("Processed names count: " + processedNames.size()); | |
| // Distinct ages | |
| List<Integer> distinctAges = employees.stream() | |
| .map(Employee::age) | |
| .distinct() | |
| .sorted() | |
| .collect(Collectors.toList()); | |
| System.out.println("Distinct ages: " + distinctAges); | |
| } | |
| /** | |
| * Demonstrates various collection operations and custom collectors | |
| * Shows different ways to collect stream results | |
| */ | |
| private static void collectionOperations(List<Employee> employees) { | |
| // Collect to List | |
| List<String> namesList = employees.stream() | |
| .map(Employee::name) | |
| .collect(Collectors.toList()); | |
| System.out.println("Names list size: " + namesList.size()); | |
| // Collect to Set (removes duplicates) | |
| Set<String> citiesSet = employees.stream() | |
| .map(Employee::address) | |
| .collect(Collectors.toSet()); | |
| System.out.println("Unique cities: " + citiesSet.size()); | |
| // Collect to Map (id -> name) | |
| Map<Integer, String> idToNameMap = employees.stream() | |
| .collect(Collectors.toMap(Employee::id, Employee::name)); | |
| System.out.println("ID to Name map size: " + idToNameMap.size()); | |
| // Joining strings | |
| String allNames = employees.stream() | |
| .map(Employee::name) | |
| .collect(Collectors.joining(", ", "[", "]")); | |
| System.out.println("Joined names length: " + allNames.length()); | |
| // Partitioning by condition | |
| Map<Boolean, List<Employee>> partitionedBySalary = employees.stream() | |
| .collect(Collectors.partitioningBy(e -> e.salary() > 25000)); | |
| System.out.println("High earners: " + partitionedBySalary.get(true).size()); | |
| System.out.println("Low earners: " + partitionedBySalary.get(false).size()); | |
| // Custom collector - concatenating departments | |
| String allDepartments = employees.stream() | |
| .map(Employee::departNames) | |
| .distinct() | |
| .collect(Collectors.joining(" | ")); | |
| System.out.println("All departments: " + allDepartments); | |
| // Collecting statistics | |
| var ageStats = employees.stream() | |
| .collect(Collectors.summarizingInt(Employee::age)); | |
| System.out.println("Age statistics: " + ageStats); | |
| } | |
| } | |
| /** | |
| * Additional utility class demonstrating Stream creation and parallel | |
| * processing | |
| */ | |
| class StreamCreationAndParallelProcessing { | |
| /** | |
| * Demonstrates different ways to create streams | |
| */ | |
| public static void streamCreationExamples() { | |
| System.out.println("\n=== STREAM CREATION EXAMPLES ==="); | |
| // From array | |
| String[] names = { "Alice", "Bob", "Charlie" }; | |
| long count = Arrays.stream(names).count(); | |
| System.out.println("Array stream count: " + count); | |
| // From range | |
| int sum = IntStream.rangeClosed(1, 10).sum(); | |
| System.out.println("Sum 1-10: " + sum); | |
| // From builder | |
| Stream<String> builderStream = Stream.<String>builder() | |
| .add("a").add("b").add("c").build(); | |
| System.out.println("Builder stream count: " + builderStream.count()); | |
| // From generate | |
| List<Double> randomNumbers = Stream.generate(Math::random) | |
| .limit(5) | |
| .collect(Collectors.toList()); | |
| System.out.println("Random numbers generated: " + randomNumbers.size()); | |
| // From iterate | |
| List<Integer> powers = Stream.iterate(1, n -> n * 2) | |
| .limit(10) | |
| .collect(Collectors.toList()); | |
| System.out.println("Powers of 2: " + powers); | |
| } | |
| /** | |
| * Demonstrates parallel stream processing | |
| */ | |
| public static void parallelProcessingExample(List<Employee> employees) { | |
| System.out.println("\n=== PARALLEL PROCESSING EXAMPLES ==="); | |
| // Sequential processing time | |
| long startTime = System.currentTimeMillis(); | |
| double avgSalarySequential = employees.stream() | |
| .mapToDouble(Employee::salary) | |
| .average() | |
| .orElse(0.0); | |
| long sequentialTime = System.currentTimeMillis() - startTime; | |
| // Parallel processing time | |
| startTime = System.currentTimeMillis(); | |
| double avgSalaryParallel = employees.parallelStream() | |
| .mapToDouble(Employee::salary) | |
| .average() | |
| .orElse(0.0); | |
| long parallelTime = System.currentTimeMillis() - startTime; | |
| System.out.println("Sequential avg salary: " + avgSalarySequential); | |
| System.out.println("Parallel avg salary: " + avgSalaryParallel); | |
| System.out.println("Sequential time: " + sequentialTime + "ms"); | |
| System.out.println("Parallel time: " + parallelTime + "ms"); | |
| // Parallel grouping | |
| Map<String, List<Employee>> parallelGrouping = employees.parallelStream() | |
| .collect(Collectors.groupingBy(Employee::departNames)); | |
| System.out.println("Parallel grouping departments: " + parallelGrouping.keySet()); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment