Definition
- map(Employee::getName) extracts the name from each employee.
- collect(Collectors.toSet()) gathers names into a
Setthat holds each value once. - Deduplication is automatic: the set uses
equalsandhashCodeto detect duplicates. - No guaranteed order:
toSet()returns aHashSetby default. - For ordered sets, use
toCollection(TreeSet::new)ortoCollection(LinkedHashSet::new).
At the National Bank of India, Priya compiles a mailing list of unique employee names. If two employees share the same name, it appears only once in the list.
Understanding the Concepts
What does collecting into a Set achieve?
A Set stores each element only once, determined by equals and hashCode. Collecting names into a set automatically removes duplicate names without needing an explicit distinct() call. The result is the set of unique names.
How do you implement it?
package com.bank.hr;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
public class CollectToSet {
record Employee(String id, String name, String department, BigDecimal salary) {}
public static void main(String[] args) {
List<Employee> staff = List.of(
new Employee("SAV2001", "Rajesh", "TRADING", new BigDecimal("1800000")),
new Employee("SAV2002", "Priya", "RISK", new BigDecimal("1200000")),
new Employee("SAV2003", "Rajesh", "OPERATIONS", new BigDecimal("900000")),
new Employee("SAV2004", "Meera", "TRADING", new BigDecimal("1500000")),
new Employee("SAV2005", "Priya", "COMPLIANCE", new BigDecimal("1050000"))
);
Set<String> uniqueNames = staff.stream()
.map(Employee::name)
.collect(Collectors.toSet());
System.out.println("Unique names: " + uniqueNames);
System.out.println("Count: " + uniqueNames.size());
}
}
Unique names: [Meera, Priya, Rajesh]
Count: 3
How do you control the set type and ordering?
// Sorted (TreeSet): alphabetical order
TreeSet<String> sorted = staff.stream()
.map(Employee::name)
.collect(Collectors.toCollection(TreeSet::new));
// [Meera, Priya, Rajesh]
// Insertion order (LinkedHashSet): first-seen order
LinkedHashSet<String> insertionOrder = staff.stream()
.map(Employee::name)
.collect(Collectors.toCollection(LinkedHashSet::new));
// [Rajesh, Priya, Meera] – first occurrence order
How is toSet() different from distinct().toList()?
| Approach | Result type | Uniqueness | Order |
|---|---|---|---|
| toSet() | Set | By set contract | Unordered (HashSet) |
| distinct().toList() | List | By distinct + equals | Encounter order preserved |
| toCollection(TreeSet::new) | TreeSet | By comparator | Sorted |
What are common mistakes?
Mistake: Assuming toSet() preserves insertion order.
// WRONG assumption: order is preserved
Set<String> names = staff.stream().map(Employee::name).collect(Collectors.toSet());
// Iteration order is unpredictable (HashSet)
// CORRECT for insertion order
LinkedHashSet<String> ordered = staff.stream()
.map(Employee::name)
.collect(Collectors.toCollection(LinkedHashSet::new));
What about custom objects and equals/hashCode?
For custom objects, deduplication depends entirely on correct equals and hashCode. If those are wrong, the set will not deduplicate as expected.
// Records automatically generate equals/hashCode from all components
record AccountId(String branch, int number) {}
Set<AccountId> uniqueAccounts = transactions.stream()
.map(Transaction::accountId)
.collect(Collectors.toSet());
// Correct deduplication because record equals checks all fields
What about null elements?
HashSet allows one null element, but TreeSet throws NullPointerException because it needs to compare elements. Filter nulls before collecting into a TreeSet.
What should a senior engineer know?
toSet() gives no ordering guarantee and no control over the concrete type. When ordering or a specific set type matters, use toCollection with a supplier. For custom objects, verify that equals and hashCode are correct before relying on set deduplication.
What are common interview follow-up questions?
- "How do you get a sorted set?" Use
toCollection(TreeSet::new). - "What if equals/hashCode are wrong?" The set will not deduplicate correctly.
- "How is toSet different from distinct?"
toSetreturns aSet;distinctreturns aStreamthat can be collected into any structure.
Visual Overview
Input: [Rajesh, Priya, Rajesh, Meera, Priya]
│
│ collect(toSet())
▼
┌──────────────────────────────┐
│ HashSet<String> │
│ {Rajesh, Priya, Meera} │
│ ← duplicates removed │
│ ← order not guaranteed │
└──────────────────────────────┘
Key Takeaway
Collecting names into a Set with map(getName).collect(toSet()) automatically removes duplicates because a set holds each element only once by equals and hashCode. No explicit distinct() call is needed. At the National Bank of India, Priya uses this for mailing lists where each name should appear once.
The default toSet() returns a HashSet with no guaranteed iteration order. For sorted order, use toCollection(TreeSet::new). For insertion order (first-seen order), use toCollection(LinkedHashSet::new). The choice depends on whether the consumer needs ordering.
For custom objects, deduplication is only as good as their equals and hashCode. If those are not implemented correctly, the set will not dedupe as expected. Records are safe because they auto-generate correct equals and hashCode from all components.
Remember one sentence: toSet() collects distinct values automatically because a set holds each element once, but use toCollection with a supplier when ordering matters.
---