This example shows how to maintain or preserve the insertion order of the elements in Java HashSet. The HashSet class may not maintain the insertion order of the elements.
How to preserve the insertion order of the elements in Java HashSet?
Let’s first see what the HashSet Java document says about the element order.
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the order will remain constant over time.
So the document clearly says that the order of the elements returned by the HashSet Iterator may not remain constant over time. Let’s now see an example of that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.util.HashSet; import java.util.Set; public class PreserveHashSetOrderExample { public static void main(String[] args) { Set<Integer> hSetNumbers = new HashSet<Integer>(); hSetNumbers.add(13); hSetNumbers.add(42); hSetNumbers.add(45); hSetNumbers.add(12); for(Integer number : hSetNumbers){ System.out.println(number); } } } |
Output
1 2 3 4 |
42 12 13 45 |
As we can see from the output, the elements returned in a different order than the insertion order.
So now back to the original question, how do we maintain the insertion order in the HashSet? The short answer is we cannot. It is by design of the HashSet class. You may get the elements in the same order as they were inserted into HashSet, but it is not guaranteed.
If the requirement is to have a Set functionality of uniqueness but still needs to preserve the insertion order of the elements, the LinkedHashSet class should be used instead of the HashSet class. This is what the LinkedHashSet document says.
Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet in that it maintains a doubly-linked list running through all of its entries. This linked list defines the iteration ordering, which is the order in which elements were inserted into the set (insertion-order).
So the LinkedHashSet class is designed to offer the Set functionality that HashSet provides while maintaining the insertion order of the elements because it maintains a doubly-linked list of the entries.
1 2 3 4 5 6 7 8 9 10 |
Set<Integer> setNumbers = new LinkedHashSet<Integer>(); setNumbers.add(13); setNumbers.add(42); setNumbers.add(45); setNumbers.add(12); for(Integer number : setNumbers){ System.out.println(number); } |
Output
1 2 3 4 |
13 42 45 12 |
As we can see from the output, the elements returned by the LinkedHashSet iterator are returned in the same order in which they were inserted.
How can I convert the HashSet to a LinkedHashSet?
If you have an existing HashSet object, you can convert it to a LinkedHashSet object using the below given copy constructor.
1 |
public LinkedHashSet(Collection<? extends E> collection) |
It creates a LinkedHashSet object containing all the elements of the specified collection object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Set<Integer> hSetNumbers = new HashSet<Integer>(); hSetNumbers.add(13); hSetNumbers.add(42); hSetNumbers.add(45); hSetNumbers.add(12); /* * To convert HashSet to LinkedHashSet, use * the copy constructor */ LinkedHashSet<Integer> lhSetNumbers = new LinkedHashSet<Integer>(hSetNumbers); for(Integer number : lhSetNumbers){ System.out.println(number); } |
Output
1 2 3 4 |
42 12 13 45 |
As we can see from the output, the elements are still not in the insertion order. That is because, when we create the LinkedHashSet object from the HashSet object, the elements are inserted in the LinkedHashSet in the order returned by the HashSet iterator.
So what is the benefit? Well, the element order we see in the output will remain constant in the LinkedHashSet from now on while the HashSet does not guarantee that. If we create a new LinkedHashSet object instead of converting from the HashSet, this problem does not arise.
This example is a part of the HashSet in Java Tutorial with Examples.
Please let me know your views in the comments section below.
References:
Java 8 HashSet