Hashset Java Example (original) (raw)
1. Introduction
The HashSet class is a part of the Java Collection API since JDK 1.2. It extends from the AbstractSet class and implements the Set Java interface. It uses HashMap internally.
Figure 1 HashSet
You can also check the Java Set Example in the following video:
Java Set Example – Video
The HashSet
class contains unique elements. It permits the null
element. It does not maintain the insertion order and is not thread-safe. In this example, I will demonstrate the following items:
- How to create a
HashSet
object - How to read, add, remove, and iterate elements in a
HashSet
- Compare
HashSet
toTreeSet
- Compare
HashSet
toLinkedHashSet
2. Technologies Used
The example code in this article was built and run using:
- Java 11
- Maven 3.3.9
- Eclipse Oxygen
- Junit 4.12
3. Maven Project
3.1 Dependencies
I will include Junit
in the pom.xml
.
4.0.0 jcg.zheng.demo java-hashset-demo 0.0.1-SNAPSHOT src maven-compiler-plugin 3.8.0 11 junit junit 4.12
4. JUnit Test
4.1 How to Construct HashSet
The HashSet
class has four constructors:
HashSet()
– Constructs a new empty set with default initial capacity (16) and load factor (0.75).HashSet(int initialCapacity)
– Constructs a new empty set with the specified initial capacity and default load factor (0.75).HashSet(int initialCapacity, float loadFactor)
– Constructs a new empty set with the specified initial capacity and the specified load factor.HashSet(Collection c)
– Constructs a new set containing the elements in the specified collection.
In this step, I will show how to create a Hashset
object via these four constructors. I emphasize the HashSet(Collection c)
constructor with the following tests:
via_collection_list
() – create aHashSet
via aList
objectvia_collection_set
() – create aHashSet
via aSet
objectvia_stream
() – create aHashSet
viaStream.of
HashSet_ConstructorTest.java
package jcg.zheng.demo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue;
import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream;
import org.junit.Test;
public class HashSet_ConstructorTest {
@Test
public void via_collection_list() {
HashSet<String> fromAnotherCollection = new HashSet<>(Arrays.asList("Mary", "Zheng"));
assertFalse(fromAnotherCollection.isEmpty());
assertTrue(fromAnotherCollection.contains("Mary"));
assertTrue(fromAnotherCollection.contains("Zheng"));
}
@Test
public void via_collection_set() {
Set<String> fromCollectionUtils = Collections.singleton("Mary");
assertFalse(fromCollectionUtils.isEmpty());
assertTrue(fromCollectionUtils.contains("Mary"));
}
@Test
public void via_default_constructor() {
// Default initial capacity is 16
// Default load factor is 0.75
HashSet<String> createdByDefaultConstructor = new HashSet<>();
assertTrue(createdByDefaultConstructor.isEmpty());
}
@Test
public void via_initialCapacity_constructor() {
// initial capacity is 0
// Default load factor is 0.75
HashSet<String> createdByDefaultConstructor = new HashSet<>(0);
assertTrue(createdByDefaultConstructor.isEmpty());
}
@Test
public void via_initialCapacity_loadfactor_constructor() {
// initial capacity is 0
// load factor is 1
HashSet<String> createdByDefaultConstructor = new HashSet<>(0, 1);
assertTrue(createdByDefaultConstructor.isEmpty());
}
@Test
public void via_list() {
List<String> listHasDuplicates = Arrays.asList("Mary", "Zheng", "Mary", "Zheng");
assertEquals(4, listHasDuplicates.size());
HashSet<String> fromList = new HashSet<>(listHasDuplicates);
assertEquals(2, fromList.size());
}
@Test
public void via_stream() {
HashSet<String> fromStream = Stream.of("Mary", "Zheng").collect(Collectors.toCollection(HashSet::new));
assertFalse(fromStream.isEmpty());
assertTrue(fromStream.contains("Mary"));
assertTrue(fromStream.contains("Zheng"));
}
@Test
public void via_via_anonymous_collection() {
@SuppressWarnings("serial")
HashSet<String> fromAnonymousClass = new HashSet<>() {
{
add("Mary");
add("Zheng");
}
};
assertFalse(fromAnonymousClass.isEmpty());
assertTrue(fromAnonymousClass.contains("Mary"));
assertTrue(fromAnonymousClass.contains("Zheng"));
}
}
Output
Running jcg.zheng.demo.HashSet_ConstructorTest Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
4.2 HashSet Common Methods
There are several common methods in HashSet:
boolean isEmpty()
– Returnstrue
if this set contains no elements.Iterator<E> iterator()
– Returns an iterator over the elements in this set.boolean add(E e)
– Adds the specified element to this set if it is not already present. It has O(1) complexity.boolean remove(Object o)
– Removes the specified element from this set if it is present. It has O(1) complexity.boolean contains(Object o)
– Returns true if this set contains the specified element. It has O(1) complexity.int size()
– Returns the number of elements in this set. It has O(1) complexity.
HashSet
is not thread safe because it throws ConcurrentModificationException
if multiple threads access a HashSet
object concurrently, and at least one of the threads modifies the set. In this step, I will create test methods to demonstrate.
not_thread_safe_cannot_modify_while_iterate()
– Iterate and modify aHashSet
object by calling theremove()
method will throwConcurrentModificationException
use_iterator_remove
– it’s ok to remove the element via iterator.
HashSetTest.java
package jcg.zheng.demo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue;
import java.util.HashSet; import java.util.Iterator; import java.util.Set;
import org.junit.Test;
public class HashSetTest {
private Set<String> testClass = new HashSet<>();
@Test
public void can_add_null() {
assertTrue(testClass.isEmpty());
testClass.add(null);
assertFalse(testClass.isEmpty());
boolean removed = testClass.remove(null);
assertTrue(removed);
assertTrue(testClass.isEmpty());
}
@Test
public void can_read_while_iterate() {
testClass.add("Mary");
testClass.add("Zheng");
Iterator<String> iterator = testClass.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
Iterator<String> iterator2 = testClass.iterator();
while (iterator2.hasNext()) {
System.out.println("\titerator2 " + iterator2.next());
}
}
testClass.clear();
assertTrue(testClass.isEmpty());
}
@Test
public void no_duplicate() {
assertTrue(testClass.isEmpty());
boolean added = testClass.add(null);
assertTrue(added);
assertFalse(testClass.isEmpty());
added = testClass.add("Mary");
assertTrue(added);
assertEquals(2, testClass.size());
added = testClass.add(null);
assertFalse(added);
added = testClass.add("Mary");
assertFalse(added);
boolean removed = testClass.remove("Mary");
assertTrue(removed);
assertEquals(1, testClass.size());
removed = testClass.remove("Mary");
assertFalse(removed);
}
@Test(expected = java.util.ConcurrentModificationException.class)
public void not_thread_safe_cannot_modify_while_iterate() {
testClass.add("Mary");
testClass.add("Zheng");
Iterator<String> iterator = testClass.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("Zheng".equalsIgnoreCase(item)) {
testClass.remove(item);// will throw exception
}
}
}
@Test
public void order_is_not_same_as_inserted() {
for (int i = 0; i < 19; i++) {
testClass.add(String.valueOf(i));
}
// [11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
System.out.println(testClass.toString());
}
@Test
public void use_iterator_remove() {
testClass.add("Mary");
testClass.add("Zheng");
Iterator<String> iterator = testClass.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("Zheng".equalsIgnoreCase(item)) {
iterator.remove();
}
}
assertEquals(1, testClass.size());
assertTrue(testClass.contains("Mary"));
assertFalse(testClass.contains("Zheng"));
}
}
Output
Running jcg.zheng.demo.HashSetTest [11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Zheng iterator2 Zheng iterator2 Mary Mary iterator2 Zheng iterator2 Mary Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.195 sec
4.3 Compare to TreeSet
The TreeSet
class extends from AbstractSet
and the elements are ordered based on their natural ordering. TreeSet
has unique element like HashSet
. But TreeSet
cannot have the null
element.
In this step, I will use test methods to compare HashSet
to TreeSet
.
CompareToTreeSetTest.java
package jcg.zheng.demo;
import static org.junit.Assert.assertEquals;
import java.util.Arrays; import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.TreeSet;
import org.junit.Test;
public class CompareToTreeSetTest {
private String[] listHasDuplicates = { "Shan", "Mary", "Mary", "Zheng", "Zheng" };
private Set<String> treeSet = new TreeSet<>();
@Test
public void HashSet_is_not_sorted_can_have_null() {
listHasDuplicates[listHasDuplicates.length - 1] = null;
assertEquals(5, listHasDuplicates.length);
Set<String> notOrderHashset = new HashSet<>(Arrays.asList(listHasDuplicates));
System.out.println(notOrderHashset);
assertEquals(4, notOrderHashset.size());
}
@Test(expected=ConcurrentModificationException.class)
public void not_thread_safe_because_cannot_modify_while_iterate() {
treeSet.add("Mary");
treeSet.add("Zheng");
treeSet.add("Tom");
Iterator<String> iterator = treeSet.iterator();
while (iterator.hasNext()) {
iterator.next();
treeSet.add("Test");
}
}
@Test(expected = NullPointerException.class)
public void TreeSet_can_not_have_null() {
treeSet.add(null);
}
@Test
public void TreeSet_is_sorted() {
assertEquals(5, listHasDuplicates.length);
TreeSet<String> orderedTreeSet = new TreeSet<>(Arrays.asList(listHasDuplicates));
System.out.println(orderedTreeSet);
assertEquals(3, orderedTreeSet.size());
assertEquals("Mary", orderedTreeSet.first());
assertEquals("Zheng", orderedTreeSet.last());
}
}
Output
Running jcg.zheng.demo.CompareToTreeSetTest [Mary, Shan, Zheng] [null, Shan, Zheng, Mary] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.117 sec
Results :
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
4.4 Compare to LinkedHashSet
The LinkedHashSet
class extends from HashSet
. The only difference between them is that LinkedHashSet
maintains the insertion order. In this step, I will create test methods to compare HashSet
to LinkedHashSet
.
CompareToLinkedHashSetTest.java
package jcg.zheng.demo;
import static org.junit.Assert.assertEquals;
import java.util.Arrays; import java.util.LinkedHashSet;
import org.junit.Test;
public class CompareToLinkedHashSetTest {
private String[] listHasDuplicates = { "Shan", "Mary", "Mary", "Zheng", "Zheng" };
private LinkedHashSet<String> setObj;
@Test
public void is_not_sorted_can_have_null() {
assertEquals(5, listHasDuplicates.length);
listHasDuplicates[listHasDuplicates.length - 1] = null;
assertEquals(5, listHasDuplicates.length);
setObj = new LinkedHashSet<>(Arrays.asList(listHasDuplicates));
System.out.println(setObj);
assertEquals(4, setObj.size());
}
@Test
public void LinkedHasSet_keeps_insertion_order() {
assertEquals(5, listHasDuplicates.length);
setObj = new LinkedHashSet<>(Arrays.asList(listHasDuplicates));
assertEquals(3, setObj.size());
//always "Shan", "Mary", "Zheng" order
System.out.println(setObj);
}
}
Output
Running jcg.zheng.demo.CompareToLinkedHashSetTest [Shan, Mary, Zheng] [Shan, Mary, Zheng, null] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.135 sec
5. Summary
In this example, I demonstrated several ways to create a HashSet
object and how to use its common methods. I also compared HashSet
to TreeSet
and LinkedHashSet
.
HashSet | LinkedHashSet | TreeSet | |
---|---|---|---|
Unique Elements | Yes | Yes | Yes |
Permit Null Element | Yes | Yes | No |
Maintain Insertion Order | No | Yes | No |
Is Sorted | No | No | Yes |
Is thread-safe | No | No | No |
6. More articles
7. Download the Source Code
This example consists of a Maven project which contains several Junit tests to demonstrate the usage of the HashSet
Class.
Download
You can download the full source code of this example here: Hashset Java Example
Last updated on Apr. 23rd, 2021
Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.