Home/Java/Set in Java

Set in Java

Learn about collections that store unique elements only

💡 Think of a Set like a collection of unique stickers - you can't have two of the exact same sticker! If you try to add a sticker you already have, nothing happens. It's perfect for when you want to make sure there are no duplicates!

🎯 What is a Set?

A Set is a collection that contains no duplicate elements. Each element can appear at most once. Sets model the mathematical set abstraction and are perfect for membership testing, removing duplicates, and set operations.

BasicHashSet.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.HashSet;
import java.util.Set;
public class BasicHashSet {
public static void main(String[] args) {
// Creating a HashSet
Set<String> colors = new HashSet<>();
// Adding elements
colors.add("Red"); // true - added successfully
colors.add("Blue"); // true - added successfully
colors.add("Green"); // true - added successfully
colors.add("Red"); // false - duplicate! Not added
System.out.println("Colors: " + colors); // Only 3 elements!
System.out.println("Size: " + colors.size()); // 3
// Checking if element exists
System.out.println("Has Blue? " + colors.contains("Blue")); // true
System.out.println("Has Yellow? " + colors.contains("Yellow")); // false
// Removing elements
colors.remove("Blue");
System.out.println("After removing Blue: " + colors);
// Iterating through set
System.out.println("\nAll colors:");
for (String color : colors) {
System.out.println("- " + color);
}
// Clear all elements
colors.clear();
System.out.println("After clear, empty? " + colors.isEmpty()); // true
}
}

🔍 📦 Types of Sets

Java provides different Set implementations with different characteristics:

1

HashSet

Fastest performance, uses hashing, no guaranteed order

2

LinkedHashSet

Maintains insertion order, slightly slower than HashSet

3

TreeSet

Elements sorted in natural order or by comparator, slowest

4

EnumSet

Specialized set for enum types, extremely fast and compact

ComparingSetTypes.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.*;
public class ComparingSetTypes {
public static void main(String[] args) {
// Same elements added to different sets
String[] elements = {"Banana", "Apple", "Orange", "Apple", "Grape"};
// 1. HashSet - Fast, no order
Set<String> hashSet = new HashSet<>();
for (String fruit : elements) {
hashSet.add(fruit);
}
System.out.println("HashSet (random order): " + hashSet);
// Example output: [Grape, Apple, Orange, Banana]
// 2. LinkedHashSet - Maintains insertion order
Set<String> linkedHashSet = new LinkedHashSet<>();
for (String fruit : elements) {
linkedHashSet.add(fruit);
}
System.out.println("LinkedHashSet (insertion order): " + linkedHashSet);
// Output: [Banana, Apple, Orange, Grape]
// 3. TreeSet - Sorted order
Set<String> treeSet = new TreeSet<>();
for (String fruit : elements) {
treeSet.add(fruit);
}
System.out.println("TreeSet (sorted order): " + treeSet);
// Output: [Apple, Banana, Grape, Orange]
System.out.println("\nAll sets have same size: " + hashSet.size());
// All have 4 elements (duplicate "Apple" removed)
}
}

🧹 Real-World Example: Removing Duplicates

RemoveDuplicates.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.*;
public class RemoveDuplicates {
public static void main(String[] args) {
// List with many duplicates
List<Integer> numbersWithDuplicates = Arrays.asList(
1, 2, 3, 2, 4, 1, 5, 3, 6, 4, 7, 5, 8, 1, 9, 2
);
System.out.println("Original list: " + numbersWithDuplicates);
System.out.println("Size: " + numbersWithDuplicates.size());
// Method 1: Using HashSet (fastest, no order)
Set<Integer> uniqueNumbers = new HashSet<>(numbersWithDuplicates);
System.out.println("\nUnique numbers (HashSet): " + uniqueNumbers);
System.out.println("Size: " + uniqueNumbers.size());
// Method 2: Using LinkedHashSet (keeps insertion order)
Set<Integer> uniqueOrdered = new LinkedHashSet<>(numbersWithDuplicates);
System.out.println("\nUnique numbers (ordered): " + uniqueOrdered);
// Method 3: Using TreeSet (sorted)
Set<Integer> uniqueSorted = new TreeSet<>(numbersWithDuplicates);
System.out.println("\nUnique numbers (sorted): " + uniqueSorted);
// Converting back to list if needed
List<Integer> uniqueList = new ArrayList<>(uniqueSorted);
System.out.println("\nBack to list: " + uniqueList);
}
// Utility method to remove duplicates
public static <T> List<T> removeDuplicates(List<T> list) {
return new ArrayList<>(new LinkedHashSet<>(list));
}
}

🌳 TreeSet: Automatic Sorting

TreeSetSorting.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.*;
public class TreeSetSorting {
public static void main(String[] args) {
// TreeSet automatically sorts elements
TreeSet<Integer> scores = new TreeSet<>();
// Add scores in random order
scores.add(85);
scores.add(92);
scores.add(78);
scores.add(95);
scores.add(88);
scores.add(78); // Duplicate - won't be added
System.out.println("Scores (auto-sorted): " + scores);
// Output: [78, 85, 88, 92, 95]
// TreeSet specific methods
System.out.println("\nLowest score: " + scores.first()); // 78
System.out.println("Highest score: " + scores.last()); // 95
// Navigation methods
System.out.println("Score lower than 90: " + scores.lower(90)); // 88
System.out.println("Score higher than 85: " + scores.higher(85)); // 88
System.out.println("Ceiling of 86: " + scores.ceiling(86)); // 88 (>= 86)
System.out.println("Floor of 86: " + scores.floor(86)); // 85 (<= 86)
// Subset operations
System.out.println("\nScores from 80 to 90: " + scores.subSet(80, 90));
System.out.println("Scores above 90: " + scores.tailSet(90));
System.out.println("Scores below 90: " + scores.headSet(90));
// Descending order
System.out.println("\nDescending order: " + scores.descendingSet());
// Custom sorting with Comparator
TreeSet<String> names = new TreeSet<>(Collections.reverseOrder());
names.addAll(Arrays.asList("Alice", "David", "Bob", "Charlie"));
System.out.println("\nNames (reverse order): " + names);
// Output: [David, Charlie, Bob, Alice]
}
}

👥 Real-World Example: Unique Visitors Tracker

UniqueVisitors.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import java.util.*;
public class UniqueVisitors {
private Set<String> visitors;
private Map<String, Integer> visitCounts;
public UniqueVisitors() {
this.visitors = new HashSet<>();
this.visitCounts = new HashMap<>();
}
// Record a visit
public void recordVisit(String username) {
visitors.add(username); // Add to unique visitors
// Count total visits
visitCounts.put(username, visitCounts.getOrDefault(username, 0) + 1);
System.out.println(username + " visited. Total visits: " +
visitCounts.get(username));
}
// Get unique visitor count
public int getUniqueVisitorCount() {
return visitors.size();
}
// Get total visit count
public int getTotalVisitCount() {
return visitCounts.values().stream().mapToInt(Integer::intValue).sum();
}
// Check if user has visited
public boolean hasVisited(String username) {
return visitors.contains(username);
}
// Get all unique visitors
public Set<String> getAllVisitors() {
return new TreeSet<>(visitors); // Return sorted
}
// Print statistics
public void printStats() {
System.out.println("\n=== Visitor Statistics ===");
System.out.println("Unique visitors: " + getUniqueVisitorCount());
System.out.println("Total visits: " + getTotalVisitCount());
System.out.println("\nVisit counts:");
// Sort by visit count
visitCounts.entrySet().stream()
.sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
.forEach(e -> System.out.println(" " + e.getKey() + ": " +
e.getValue() + " visits"));
}
public static void main(String[] args) {
UniqueVisitors tracker = new UniqueVisitors();
// Simulate website visits
tracker.recordVisit("alice");
tracker.recordVisit("bob");
tracker.recordVisit("alice"); // Repeat visitor
tracker.recordVisit("charlie");
tracker.recordVisit("bob"); // Repeat visitor
tracker.recordVisit("alice"); // Repeat visitor
tracker.recordVisit("david");
tracker.printStats();
// Check specific user
System.out.println("\nHas 'eve' visited? " + tracker.hasVisited("eve"));
System.out.println("Has 'alice' visited? " + tracker.hasVisited("alice"));
}
}

🔄 Set Operations: Union, Intersection, Difference

SetOperations.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.*;
public class SetOperations {
public static void main(String[] args) {
Set<String> teamA = new HashSet<>(Arrays.asList("Alice", "Bob", "Charlie", "David"));
Set<String> teamB = new HashSet<>(Arrays.asList("Charlie", "David", "Eve", "Frank"));
System.out.println("Team A: " + teamA);
System.out.println("Team B: " + teamB);
// 1. UNION - All unique members from both teams
Set<String> union = new HashSet<>(teamA);
union.addAll(teamB);
System.out.println("\nUnion (all members): " + union);
// [Alice, Bob, Charlie, David, Eve, Frank]
// 2. INTERSECTION - Members in both teams
Set<String> intersection = new HashSet<>(teamA);
intersection.retainAll(teamB);
System.out.println("Intersection (in both): " + intersection);
// [Charlie, David]
// 3. DIFFERENCE - Members only in Team A
Set<String> difference = new HashSet<>(teamA);
difference.removeAll(teamB);
System.out.println("Difference (only in A): " + difference);
// [Alice, Bob]
// 4. SYMMETRIC DIFFERENCE - Members in one team but not both
Set<String> symmetricDiff = new HashSet<>(union);
symmetricDiff.removeAll(intersection);
System.out.println("Symmetric Difference: " + symmetricDiff);
// [Alice, Bob, Eve, Frank]
// 5. SUBSET - Is Team A subset of Union?
boolean isSubset = union.containsAll(teamA);
System.out.println("\nIs Team A subset of Union? " + isSubset); // true
// 6. DISJOINT - Do sets have no common elements?
Set<String> teamC = new HashSet<>(Arrays.asList("George", "Helen"));
boolean areDisjoint = Collections.disjoint(teamA, teamC);
System.out.println("Are Team A and C disjoint? " + areDisjoint); // true
}
}

🔑 Key Concepts

No Duplicates

Each element must be unique based on equals() method

Adding 'Apple' twice only stores it once

No Ordering Guarantee (HashSet)

Elements may not maintain insertion order

Add [A, B, C] might give you [C, A, B]

Sorted Order (TreeSet)

Elements automatically sorted

Add [3, 1, 2] gives you [1, 2, 3]

Fast Lookup

Checking if element exists is very fast O(1) for HashSet

set.contains('Apple') is lightning fast

Best Practices

  • Use HashSet for best performance when order doesn't matter
  • Use LinkedHashSet when you need predictable iteration order
  • Use TreeSet when you need sorted elements
  • Objects stored in Set must properly implement equals() and hashCode()
  • Use Set for removing duplicates from collections
  • Prefer Set interface type over implementation in declarations
  • Consider immutable sets with Set.of() for fixed collections

💼 Interview Tips

  • HashSet uses HashMap internally with dummy values
  • TreeSet is implemented using Red-Black tree (balanced BST)
  • HashSet is O(1) for add/remove/contains, TreeSet is O(log n)
  • Elements in HashSet must have good hashCode() implementation
  • TreeSet elements must be comparable (implement Comparable or use Comparator)
  • Remember that null is allowed in HashSet (one null) but not in TreeSet
  • Know the difference between Set operations: union, intersection, difference
  • Understand that Set.equals() compares elements, not order