Java Set
- Java Set Tutorial Video
- Java Set vs. List
- Java Set Example
- Set Implementations
- Create a Set
- Generic Sets
- Set.of()
- Add Element to Set
- Iterate Set Elements
- Remove Elements From Set
- Remove All Elements From Set
- Add All Elements From Another Collection
- Remove All Elements From Another Collection
- Retain All Elements Present in Another Collection
- Set Size
- Check if Set is Empty
- Check if Set Contains Element
- Convert Java Set to List
- More Details in the JavaDoc
Jakob Jenkov |
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 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 theSet
. - 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.
Tweet | |
Jakob Jenkov |