Set: HashSet, LinkedHashSet, TreeSet
Uniqueness and the three ordering variants — plus why equals/hashCode are non-negotiable.
The Set contract: no duplicates
A Set<E> stores each distinct element at most once. add() returns false if the element was already present.
Set<String> tags = new HashSet<>();
tags.add("java");
tags.add("java"); // duplicate — silently ignored, returns false
tags.add("generics");
System.out.println(tags.size()); // 2
HashSet stores elements in a hash table. add, contains, and remove are O(1) average. Iteration order is unpredictable and may change across JVM runs.
LinkedHashSet extends HashSet and maintains a doubly-linked list of insertion order. Same O(1) operations, but iterator() yields elements in the order they were first added.
TreeSet stores elements in a balanced Red-Black tree. add, contains, and remove are O(log n). Elements are iterated in natural order (via Comparable) or a supplied Comparator. It also implements NavigableSet, giving range views (headSet, tailSet, subSet) and nearest-element queries (floor, ceiling).
Set<String> sorted = new TreeSet<>(Set.of("banana", "apple", "cherry"));
sorted.forEach(System.out::println); // apple, banana, cherry
Equals and hashCode are critical. HashSet and LinkedHashSet call hashCode() to find the bucket and equals() to confirm identity. If two logically equal objects have different hash codes, the set stores both — silently treating them as distinct. Correct equals/hashCode is not optional.