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.

Hashset Java

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:

2. Technologies Used

The example code in this article was built and run using:

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:

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:

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:

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.

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

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

Photo of Mary Zheng

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.