Java Set

Jakob Jenkov
Last update: 2020-10-13

The Java Set interface, java.util.Set, represents a collection of objects where each object in the Java Set is unique. In other words, the same object cannot occur more than once in a Java Set. The Java Set interface is a standard Java interface, and it is a subtype of the Java Collection interface, meaning Set inherits from Collection.

You can add any Java object to a Java Set. If the Set is not typed, using Java Generics, then you can even mix objects of different types (classes) in the same Set. Mixing objects of different types in the same Set is not often done in reality, however.

Java Set Tutorial Video

If you prefer video, I have made a Java Set tutorial video:

Java Set Tutorial Video

Java Set vs. List

The Java Set and Java List interfaces are quite similar to each other. Bot interfaces represents a collection of elements. However, there are some significant differences. These differences are reflected in the methods the Set and List interfaces contain.

The first difference between the Java Set and List interface is, that the same element cannot occur more than once in a Java Set. This is different from a Java List where each element can occur more than once.

The second difference between a Java Set and Java List interfaces is, that the elements in a Set has no guaranteed internal order. The elements in a List has an internal order, and the elements can be iterated in that order.

Java Set Example

Here is first a simple Java Set example to give you a feel for how sets work:

package com.jenkov.collections;

import java.util.HashSet;

public class SetExample {

    public static void main(String[] args) {

        Set setA = new HashSet();

        setA.add(element);

        System.out.println( setA.contains(element) );
    }
}

This example creates a HashSet which is one of the classes in the Java APIs that implement the Set interface. Then it adds a string object to the set, and finally it checks if the set contains the element just added.

Set Implementations

Being a Collection subtype all methods in the Collection interface are also available in the Set interface.

Since Set is an interface you need to instantiate a concrete implementation of the interface in order to use it. You can choose between the following Set implementations in the Java Collections API:

  • java.util.EnumSet
  • java.util.HashSet
  • java.util.LinkedHashSet
  • java.util.TreeSet

Each of these Set implementations behaves a little differently with respect to the order of the elements when iterating the Set, and the time (big O notation) it takes to insert and access elements in the sets.

HashSet is backed by a HashMap. It makes no guarantees about the sequence of the elements when you iterate them.

LinkedHashSet differs from HashSet by guaranteeing that the order of the elements during iteration is the same as the order they were inserted into the LinkedHashSet. Reinserting an element that is already in the LinkedHashSet does not change this order.

TreeSet also guarantees the order of the elements when iterated, but the order is the sorting order of the elements. In other words, the order in which the elements whould be sorted if you used a Collections.sort() on a List or array containing these elements. This order is determined either by their natural order (if they implement Comparable), or by a specific Comparator implementation.

There are also Set implementations in the java.util.concurrent package, but I will leave the concurrency utilities out of this tutorial.

Create a Set

Here are a few examples of how to create a Set instance:

package com.jenkov.collections;

import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

public class SetExample {

    public static void main(String[] args) {

        Set setA = new HashSet();
        Set setB = new LinkedHashSet();
        Set setC = new TreeSet();

    }
}

Generic Sets

By default you can put any Object into a Set, but from Java 5, Java Generics makes it possible to limit the types of object you can insert into a Set. Here is an example:

Set<MyObject> set = new HashSet<MyObject>();

This Set can now only have MyObject instances inserted into it. You can then access and iterate its elements without casting them. Here is how it looks:

for(MyObject anObject : set){
   //do someting to anObject...
}

It is considered good practice to alway specify a generic type for a Java Set whenever you know it. Most of the examples in this tutorial uses generic types.

For more information about Java Generics, see the Java Generics Tutorial.

Set.of()

Since Java 9 the Set interface contains a set of static factory methods that can create unmodifiable (immutable) Set instances. I will explain some of these methods in this section.

The Java Set static factory methods are called of() and take either zero or more parameters. Here is first an example of creating an empty, immutable Set using Set.of() :

Set set = Set.of();

This example creates an unmodifiable Set with no generic type specified.

Specifying a generic type of the Set returned by Set.of() looks like this:

Set<String> set3 = Set.<String>of();    

You can also create unmodifiable Set instances which contains elements of your choice. You pass these elements to the of() method. Here is an example of how creating a Set containing elements using the Set.of() method looks:

Set<String> set3 = Set.<String>of("val1", "val2", "val3");

Add Element to Set

To add elements to a Set you call its add() method. This method is inherited from the Collection interface. Here are a few examples:

Set<String> setA = new HashSet<>();

setA.add("element 1");
setA.add("element 2");
setA.add("element 3");

The three add() calls add a String instance to the set.

Iterate Set Elements

There are two ways to iterate the elements of a Java Set:

  • Using an Iterator obtained from the Set.
  • Using the for-each loop.

Both of these options are covered in the following sections.

When iterating the elements in the Set the order of the elements depends on what Set implementation you use, as mentioned earlier.

Iterate Set Using Iterator

To iterate the elements of a Set using an Java Iterator, you must first obtain an Iterator from the Set. You obtain an Iterator from a Set by calling the iterator() method. Here is an example of obtaining an Iterator from a Set:

Set<String> setA = new HashSet<>();

setA.add("element 1");
setA.add("element 2");
setA.add("element 3");

Iterator<String> iterator = set.iterator();

while(iterator.hasNext(){
  String element = iterator.next();
}

Iterate Set Using For-Each Loop

The second way to iterate the elements of a Set is by using a for-each loop. Here is how iterating the elements of a Set using a for-each loop looks:

Set set = new HashSet();

for(Object object : set) {
    String element = (String) object;
}

The Set interface implements the Java Iterable interface. That is why you can iterate the elements of a Set using the for-each loop.

If the set has a generic type specified, you can use that type as the variable type inside the for-each loop. Here is how that looks:

Set<String> set = new HashSet<>();

for(String str : set) {
    System.out.println(str);
}

This is the preferred way to use the for-each loop - in combination with the generic type specified for the Collection the for-each loop is used on.

Iterate Set Using the Java Stream API

The third way to iterate a Java Set is via the Java Stream API . To itereate a Java Set using the Java Stream API you must create a Stream from the Set. Here is an example of creating a Java Stream from a Set and iterate the Stream:

Set<String> set = new HashSet<>();

set.add("one");
set.add("two");
set.add("three");

Stream<String> stream = set.stream();

stream.forEach((element) -> 
{ System.out.println(element); });

You can read more about what options you have available in the Java Stream API in my Java Stream API tutorial.

Remove Elements From Set

You remove elements from a Java Set by calling the remove(Object o) method. Here is an example of removing an element from a Java Set:

set.remove("object-to-remove");

There is no way to remove an object based on index in a Set, since the order of the elements depends on the Set implementation.

Remove All Elements From Set

You can remove all elements from a Java Set using the clear() method. Here is an example of removing all elements from a Java Set:

set.clear();

Add All Elements From Another Collection

The Java List interface has a method called addAll() which adds all elements from another Collection (List or Set) to the Set. In set theory this corresponds to the union of the Set and the other Collection. Here is an example of adding all elements from another Set to a Java Set:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");

Set<String> set2 = new HashSet<>();
set2.add("four");

set2.addAll(set);

After executing this code example the set2 will contain the String element four, as well as the three String elements one, two and three from set.

Remove All Elements From Another Collection

The Java Set interface as a method called removeAll() which removes all elements in the Set which are also present in another Collection. In set theory, this is referred to as the difference between the Set and the other Collection. Here is an example of removing all elements from a Java Set which are also present in another Collection:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");

Set set2 = new HashSet();
set2.add("three");

set.removeAll(set2);

After running this Java example the set will contain the String elements one and two. The element three has been removed, because it was present in set2, which was given as parameter to set.removeAll(set2) .

Retain All Elements Present in Another Collection

The Java Set interface also has a method which retains all elements in the Set which are also present in another Collection. All elements found in the Set which are not present in the other Collection will be removed. In set theory this is referred to as the intersection between the Set and the other Collection. Here is an example of retaining all elements in a Java Set which are also present in another Set:

Set<String> set = new HashSet<>();
set.add("one");
set.add("two");
set.add("three");

Set<String> set2 = new HashSet<>();
set2.add("three");
set2.add("four");

set.retainAll(set2);

After running this Java code, the set will only contain the String element three. That is the only element which is present in both set and set2.

Set Size

You can check the size of a Java Set using the size() method. The size of a Set is the number of elements contained in the Set. Here is an example of reading the size of a Java Set:

Set<String> set = new HashSet<>();

set.add("123");
set.add("456");
set.add("789");

int size = set.size();

After executing this Java code the size variable will have the value 3, because the Set created in the example had 3 elements added to it.

Check if Set is Empty

You can check if a Java Set is empty, meaning it contains no elements, by calling the isEmpty() method on the Set. Here is an example of checking if a Java Set is empty:

Set<String> set = new HashSet<>();

boolean isEmpty = set.isEmpty();

After running this Java code the isEmpty variable will contain the value true, because the Set is empty (has no elements in it).

You can also check if a Set is empty by comparing the value returned by the size() method with 0. Here is an example that shows how:

Set<String> set = new HashSet<>();

boolean isEmpty = (set.size() == 0);

After running this Java code the isEmpty variable will contain the value true, because the Set size() method returns 0 - because the Set in the example contains no elements.

Check if Set Contains Element

You can check if a Java Set contains a given element (object) by calling the contains() method. Here is an example of checking if a Java Set contains a given element:

Set<String> set = new HashSet<>();

set.add("123");
set.add("456");

boolean contains123 = set.contains("123");

After running this Java code the contains123 variable will contain the value true because the Set actually contains the String 123.

To determine if the Set contains the element, the Set will internally iterate its elements and compare each element to the object passed as parameter. The comparison uses the Java equals method of the element to check if the element is equal to the parameter.

Since it is possible to add null values to a Set, it is also possible to check if the Set contains a null value. Here is how you check if a Set contains a null value:

set.add(null);

containsElement = set.contains(null);

System.out.println(containsElement);

Obviously, if the input parameter to contains() is null, the contains() method will not use the equals() method to compare against each element, but rather use the == operator.

Convert Java Set to List

You can convert a Java Set to a Java List by creating a List and calling its addAll() method, passing the Set as parameter to the addAll() method. Here is an example of converting a Java Set to a List:

Set<String> set = new HashSet<>();
set.add("123");
set.add("456");

List<String> list = new ArrayList<>();
list.addAll(set);

After running this Java example, the List will contain the String elements 123 and 456 - since these were all the elements present in the Set when List addAll(set) was called.

More Details in the JavaDoc

There is a lot more you can do with a Set, but you will have to check out the JavaDoc for more details. This text focused on the two most common operations: Adding / removing elements, and iterating the elements.

Jakob Jenkov

Featured Videos

Java Generics

Java ForkJoinPool

P2P Networks Introduction



















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next