Java HashSet
A set is a collection in which every value appears at most once. Adding a value that is already there does nothing. Sets answer the question "is this value in the collection?" very quickly. Use one to collect unique visitors, to remove duplicates from a list, or to remember which items you have already seen. Java's most used set is HashSet.
Adding and checking
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet<String> visitors = new HashSet<>();
System.out.println(visitors.add("asha"));
System.out.println(visitors.add("vikram"));
System.out.println(visitors.add("asha"));
System.out.println(visitors.size());
System.out.println(visitors.contains("vikram"));
visitors.remove("vikram");
System.out.println(visitors.contains("vikram"));
}
}true true false 2 true false
add returns true when the value was new and false when it was already in the set, which is a neat way to detect repeats. Like a HashMap, a HashSet does not keep any order.
Removing duplicates
Creating a set from a list keeps one copy of every value. A TreeSet keeps the values sorted, and a LinkedHashSet keeps them in the order they were first added:
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = List.of(5, 3, 5, 1, 3, 9, 1);
System.out.println(new TreeSet<>(numbers));
System.out.println(new LinkedHashSet<>(numbers));
List<Integer> unique = new ArrayList<>(new LinkedHashSet<>(numbers));
System.out.println(unique.size());
}
}[1, 3, 5, 9] [5, 3, 1, 9] 4
Finding repeats
The value of add makes it easy to find the first value that appears twice:
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
String[] words = {"red", "blue", "green", "blue", "red"};
HashSet<String> seen = new HashSet<>();
for (String w : words) {
if (!seen.add(w)) {
System.out.println("First repeat: " + w);
break;
}
}
}
}First repeat: blue
Set operations
Sets support the operations from mathematics. addAll gives the union, retainAll the intersection and removeAll the difference. Each one changes the set it is called on, so start from a copy:
import java.util.Set;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
Set<String> java = Set.of("Asha", "Ben", "Chitra", "Dev");
Set<String> python = Set.of("Ben", "Dev", "Esha");
Set<String> both = new TreeSet<>(java);
both.retainAll(python);
Set<String> either = new TreeSet<>(java);
either.addAll(python);
Set<String> onlyJava = new TreeSet<>(java);
onlyJava.removeAll(python);
System.out.println("Both courses: " + both);
System.out.println("Any course: " + either);
System.out.println("Only Java: " + onlyJava);
}
}Both courses: [Ben, Dev] Any course: [Asha, Ben, Chitra, Dev, Esha] Only Java: [Asha, Chitra]
Set.of creates a small fixed set, like List.of in ArrayList. Copying it into a TreeSet gives a changeable, sorted set.
Practice exercises
- Read words from a sentence into a set and print how many different words there are.
- Print the letters that appear in both "java" and "python".
- Remove duplicates from
{4, 1, 4, 2, 1, 4}and print the result in sorted order.