Hashset Java Example
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.
![Hashset Java](https://examples.javacodegeeks.com/wp-content/uploads/2020/02/hashset.jpg)
You can also check the Java Set Example in the following 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
.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg.zheng.demo</groupId> <artifactId>java-hashset-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
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.
You can download the full source code of this example here: Hashset Java Example
Last updated on Apr. 23rd, 2021