$ Map<String, Double> avgSalary = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.averagingInt(Employee::getSalary) )); COMMAND_BLOCK: Map<String, Double> avgSalary = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.averagingInt(Employee::getSalary) )); COMMAND_BLOCK: Map<String, Double> avgSalary = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.averagingInt(Employee::getSalary) )); COMMAND_BLOCK: List<Employee> employees = Arrays.asList( new Employee("Amit", "IT", "Developer", 60000), new Employee("Neha", "IT", "Tester", 50000), new Employee("Raj", "HR", "Recruiter", 40000), new Employee("Simran", "HR", "Manager", 70000), new Employee("Karan", "Sales", "Executive", 45000) ); COMMAND_BLOCK: List<Employee> employees = Arrays.asList( new Employee("Amit", "IT", "Developer", 60000), new Employee("Neha", "IT", "Tester", 50000), new Employee("Raj", "HR", "Recruiter", 40000), new Employee("Simran", "HR", "Manager", 70000), new Employee("Karan", "Sales", "Executive", 45000) ); COMMAND_BLOCK: List<Employee> employees = Arrays.asList( new Employee("Amit", "IT", "Developer", 60000), new Employee("Neha", "IT", "Tester", 50000), new Employee("Raj", "HR", "Recruiter", 40000), new Employee("Simran", "HR", "Manager", 70000), new Employee("Karan", "Sales", "Executive", 45000) ); CODE_BLOCK: { IT=55000.0, HR=55000.0, Sales=45000.0 } CODE_BLOCK: { IT=55000.0, HR=55000.0, Sales=45000.0 } CODE_BLOCK: { IT=55000.0, HR=55000.0, Sales=45000.0 } COMMAND_BLOCK: Map<String, List<String>> namesByDept = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.mapping( Employee::getName, Collectors.toList() ) )); COMMAND_BLOCK: Map<String, List<String>> namesByDept = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.mapping( Employee::getName, Collectors.toList() ) )); COMMAND_BLOCK: Map<String, List<String>> namesByDept = employees.stream() .collect(Collectors.groupingBy( Employee::getDepartment, Collectors.mapping( Employee::getName, Collectors.toList() ) )); CODE_BLOCK: { IT=[Amit, Neha], HR=[Raj, Simran], Sales=[Karan] } CODE_BLOCK: { IT=[Amit, Neha], HR=[Raj, Simran], Sales=[Karan] } CODE_BLOCK: { IT=[Amit, Neha], HR=[Raj, Simran], Sales=[Karan] } COMMAND_BLOCK: List<String> names = employees.stream() .map(Employee::getName) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList )); COMMAND_BLOCK: List<String> names = employees.stream() .map(Employee::getName) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList )); COMMAND_BLOCK: List<String> names = employees.stream() .map(Employee::getName) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList )); CODE_BLOCK: [Amit, Neha, Raj, Simran, Karan] CODE_BLOCK: [Amit, Neha, Raj, Simran, Karan] CODE_BLOCK: [Amit, Neha, Raj, Simran, Karan] CODE_BLOCK: Collector.of( supplier, accumulator, combiner, finisher ); CODE_BLOCK: Collector.of( supplier, accumulator, combiner, finisher ); CODE_BLOCK: Collector.of( supplier, accumulator, combiner, finisher ); COMMAND_BLOCK: Collector<String, StringBuilder, String> customCollector = Collector.of( StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString ); COMMAND_BLOCK: Collector<String, StringBuilder, String> customCollector = Collector.of( StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString ); COMMAND_BLOCK: Collector<String, StringBuilder, String> customCollector = Collector.of( StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString ); CODE_BLOCK: String result = Stream.of("A", "B", "C") .collect(customCollector); CODE_BLOCK: String result = Stream.of("A", "B", "C") .collect(customCollector); CODE_BLOCK: String result = Stream.of("A", "B", "C") .collect(customCollector); CODE_BLOCK: ABC CODE_BLOCK: stream.parallel().collect(...) CODE_BLOCK: stream.parallel().collect(...) CODE_BLOCK: stream.parallel().collect(...) COMMAND_BLOCK: List<String> list = new ArrayList<>(); stream.forEach(list::add); // Not thread-safe COMMAND_BLOCK: List<String> list = new ArrayList<>(); stream.forEach(list::add); // Not thread-safe COMMAND_BLOCK: List<String> list = new ArrayList<>(); stream.forEach(list::add); // Not thread-safe CODE_BLOCK: stream.parallel().collect(Collectors.toList()); CODE_BLOCK: stream.parallel().collect(Collectors.toList()); CODE_BLOCK: stream.parallel().collect(Collectors.toList()); - What is a Collector? - How collect() Works Internally - Commonly Used Built-in Collectors - Grouping and Partitioning - Downstream Collectors (Advanced) - collectingAndThen() - Creating a custom collector - Parallel streams and collectors - IT → (60000 + 50000) / 2 = 55000.0 - HR → (40000 + 70000) / 2 = 55000.0 - Sales → (45000) / 1 = 45000.0 - Append "A" → "A" - Append "B" → "AB" - Append "C" → "ABC" - Associative - Non-interfering - Build custom reduction logic