Collectors
forEach() is for side efects.
collect() is for producing a result.
Tipical side effects:
- printing, logging
- writing a file
- sending emails
- mutating external state (usually discouraged)
Collect:
- Terminal operation
- Returns a new data structure
- No side effects (ideally)
Common Collectors:
- toList()
- toSet()
- toMap()
- joining()
- groupBy()
package collectors;
import java.util.List;
import java.util.stream.Collectors;
public class CollectorsToList {
public static void main(String[] args) {
List<String> users = List.of("Alice", "Bob", "Charlie");
users.stream()
.forEach(user ->
System.out.println("Processing user: " + user)
);
List<String> clients = List.of("Alice", "Bob", "Charlie");
List<String> filteredClients =
clients.stream()
.filter(user -> user.startsWith("A"))
.collect(Collectors.toList());
System.out.println(filteredClients);
}
}
Grouping (real-world example)
Imagine an e-commerce system.
You want to group orders by status so you can:
- process payments
- prepare shipments
- show dashboards
package collectors;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.counting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CollectGroupingBy {
public static void main(String[] args) {
List<Order> orders = List.of(
new Order(1, Status.NEW),
new Order(2, Status.PAID),
new Order(3, Status.NEW),
new Order(4, Status.SHIPPED)
);
Map<Status, List<Order>> ordersByStatus = new HashMap<>();
for (Order order : orders) {
Status status = order.status();
if (!ordersByStatus.containsKey(status)) {
ordersByStatus.put(status, new ArrayList<>());
}
ordersByStatus.get(status).add(order);
}
System.out.println(
ordersByStatus.get(Status.NEW)
);
Map<Status, List<Order>> ordersByStatus_B =
orders.stream()
.collect(groupingBy(Order::status));
System.out.println(
ordersByStatus_B.get(Status.PAID)
);
Map<Status, Long> countByStatus =
orders.stream()
.collect(groupingBy(
Order::status,
counting()
));
System.out.println(countByStatus);
}
}
enum Status {
NEW, PAID, SHIPPED
}
record Order(int id, Status status) {}