Hash Sets are collections of unique items i.e no element can be repeated.
Hash Sets were designed to give us a way of adding and looking for unique values in a collection in a quick manner.
The values in a Hash Set can be either simple primitives like strings or integers as well as more complex object types like object literals or arrays.
In Java, the Hash Set is implemented as a HashSet
object.
Creation:
To create a new empty HashSet
that holds Strings
, you use the following syntax:
Set<String> mySet = new HashSet<>();
Creating an empty Set takes O(1)
time.
Constructing from iterable
The Set constructor also accepts an optional iterable object. If you pass an iterable object to the Set constructor, all the unique elements of the object will be added to the new set:
List<String> elements = new ArrayList<>(List.of("b", "c", "c", "d"));
Set<String> mySet = new HashSet<>(elements);
// mySet contains {"b", "c", "d"}
This takes O(n)
time, where n
is the number of elements in the iterable object.
Adding elements:
To add an element to the set, you use the add()
method:
List<String> elements = new ArrayList<>(List.of("b", "c", "c", "d"));
Set<String> mySet = new HashSet<>(elements);
// Adding new elements
mySet.add("x");
// Adding an existing element
mySet.add("d"); // nothing happens
// mySet contains {"b", "c", "d", "x"}
The Set first checks if that element already exists and if so, it does nothing and also doesn't raise an error.
Adding an element to a Set takes O(1)
time.
Checking if a value exists:
To check if a Set has a specific element, you use the contains()
method which returns true
if the set contains the element, otherwise, it returns false
.
List<String> elements = new ArrayList<>(List.of("b", "c", "c", "d"));
Set<String> mySet = new HashSet<>(elements);
boolean exists = mySet.contains("c"); // exists is true
exists = mySet.contains("x"); // exists becomes false
Checking if a value exists in a Set takes O(1)
time.
Removing elements:
To delete a specified element from a set, you use the remove()
method:
List<String> elements = new ArrayList<>(List.of("b", "c", "c", "d"));
Set<String> mySet = new HashSet<>(elements);
// Deleting elements
mySet.remove("c");
// Deleting a non-existent element
mySet.remove("z"); // does nothing
// mySet contains {"b", "d"}
The Set first checks if that key exists and if not, it does nothing and also doesn't raise an error, so it's safe to delete non-existing elements.
Removing an element from a Set takes O(1)
time.
Iterating over the Set values:
If we want to iterate over values of the Set
, we can use the for
loop along with the :
operator:
List<String> elements = new ArrayList<>(List.of("b", "c", "c", "d"));
Set<String> mySet = new HashSet<>(elements);
for (String val : mySet) {
System.out.println(val);
}
// This will print the following:
// b
// c
// d
Iterating over a Set
takes O(n)
time.
Space Complexity
A Set uses O(n)
space, where n
is the number of elements existing in the Set.
Assignment
Follow the Coding Tutorial and let's play with some Hash Sets.
Hint
Look at the examples above if you get stuck.
In this lesson, we will explore the concept of Hash Sets in Java. Hash Sets are a fundamental data structure that allows us to store unique elements and perform operations like adding, removing, and checking for the existence of elements efficiently. Understanding Hash Sets is crucial for solving problems that require quick lookups and ensuring uniqueness in collections.
A Hash Set is a collection that contains no duplicate elements. It is part of the Java Collections Framework and is implemented as a HashSet
object. The primary operations supported by a Hash Set include adding elements, removing elements, and checking if an element exists in the set. These operations are typically performed in constant time, O(1), making Hash Sets highly efficient for these tasks.
Set<String> mySet = new HashSet<>();
mySet.add("apple");
mySet.add("banana");
mySet.add("apple"); // Duplicate, will not be added
System.out.println(mySet); // Output: [apple, banana]
Let's delve deeper into the key concepts and techniques involved in using Hash Sets.
To create a Hash Set, you can use the following syntax:
Set<String> mySet = new HashSet<>();
To add an element to a Hash Set, use the add()
method:
mySet.add("apple");
mySet.add("banana");
To check if an element exists in a Hash Set, use the contains()
method:
boolean exists = mySet.contains("apple"); // true
To remove an element from a Hash Set, use the remove()
method:
mySet.remove("apple");
Let's look at some examples to understand how Hash Sets can be used in various contexts.
List<String> list = Arrays.asList("apple", "banana", "apple", "orange");
Set<String> uniqueSet = new HashSet<>(list);
System.out.println(uniqueSet); // Output: [apple, banana, orange]
Set<String> set1 = new HashSet<>(Arrays.asList("apple", "banana"));
Set<String> set2 = new HashSet<>(Arrays.asList("banana", "orange"));
set1.retainAll(set2);
System.out.println(set1); // Output: [banana]
When working with Hash Sets, it's important to be aware of common pitfalls and follow best practices to write efficient and maintainable code.
ConcurrentModificationException
. Use an iterator if you need to modify the set during iteration.HashSet
when you need a collection with unique elements and fast lookups.LinkedHashSet
if you need to maintain insertion order.Let's explore some advanced techniques related to Hash Sets.
You can combine two Hash Sets using the addAll()
method:
Set<String> set1 = new HashSet<>(Arrays.asList("apple", "banana"));
Set<String> set2 = new HashSet<>(Arrays.asList("banana", "orange"));
set1.addAll(set2);
System.out.println(set1); // Output: [apple, banana, orange]
Hash Sets can also store custom objects. Ensure that your custom objects override equals()
and hashCode()
methods for correct behavior.
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
Set<Person> people = new HashSet<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
Here is a complete example demonstrating the use of Hash Sets in Java:
import java.util.HashSet;
import java.util.Set;
public class HashSetExample {
public static void main(String[] args) {
// Creating a HashSet
Set<String> mySet = new HashSet<>();
// Adding elements
mySet.add("apple");
mySet.add("banana");
mySet.add("apple"); // Duplicate, will not be added
// Checking if an element exists
boolean exists = mySet.contains("apple"); // true
// Removing an element
mySet.remove("apple");
// Iterating over the set
for (String val : mySet) {
System.out.println(val);
}
}
}
When working with Hash Sets, it's important to write tests to ensure your code behaves as expected. Here are some tips for debugging and testing:
Write unit tests to verify the behavior of your Hash Set operations. Here's an example using JUnit:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.util.HashSet;
import java.util.Set;
public class HashSetTest {
@Test
public void testAdd() {
Set<String> mySet = new HashSet<>();
mySet.add("apple");
assertTrue(mySet.contains("apple"));
}
@Test
public void testRemove() {
Set<String> mySet = new HashSet<>();
mySet.add("apple");
mySet.remove("apple");
assertFalse(mySet.contains("apple"));
}
}
When solving problems related to Hash Sets, consider the following strategies:
In this lesson, we covered the basics and advanced concepts of Hash Sets in Java. We explored how to create, add, remove, and check for elements in a Hash Set. We also discussed common pitfalls, best practices, and advanced techniques. Understanding Hash Sets is essential for efficient data management and quick lookups in programming. Keep practicing and exploring further applications to master this powerful data structure.
For further reading and practice problems, check out the following resources: