Ordering of elements in Java HashSet
The second one (just using HashSet
) is only a coincidence. From the JavaDocs:
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. This class permits the null element.
The third one (LinkedHashSet
) is designed to be like that:
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). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)
Understanding order of elements in stream generated from HashSet
There is a little bit of mis-understating here indeed. A HashSet
or any Set
is not about order, unless TreeSet
that is ordered based on a Comparator
.
At the moment, under java-8 once you put elements into a HashSet
(and don't change it) - there will be an order of how the elements are laid out; but again, under the condition that you do not add or remove any of them. This can change at any point in time, so don't rely on it.
For example running this:
String[] colors = new String[] { "red", "green", "blue", "orange" };
List<String> colorsList = Arrays.asList(colors);
HashSet<String> colorsSet = new HashSet<>();
colorsSet.addAll(colorsList);
System.out.println(colorsSet);
No matter how many times under java-8 at the moment you will always get the same output:
[red, orange, green, blue]
But once you do some internal re-shuffling:
for (int i = 0; i < 1000; ++i) {
colorsSet.add("" + i);
}
for (int i = 0; i < 1000; ++i) {
colorsSet.remove("" + i);
}
System.out.println(colorsSet); // [blue, red, green, orange]
You can see that the output changes, because Set
s don't have an order.
The key point to take is that there is no order, the fact that you do see an order is not a guarantee to happen every time - there might be a build in java-8 that will break this order. And in fact that is easily observable with java-9
for example - where there is a randomization pattern for new Set
s.
If you run this multiple times, the result will differ:
Set<String> set = Set.of("red", "green", "blue", "orange");
System.out.println(set);
So obviously of you stream
from such a Set
the order will not be guaranteed and thus you will indeed see different results from run to run.
Hashset ordering issue
Coincidence. It just happens that the hashCode of Character is it’s numeric value. If you keep adding more characters than there are hash buckets in the HashSet, you’ll see that they get out of order.
Order of element in hashSet
The order of the entries in a HashMap or HashSet is predictable in theory for current generation and older implementations.
However, the prediction depends on at least:
- the hash values of the keys,
- the initial capacity of the set or map,
- the precise sequence in which the keys were added to and removed from the set / map,
- the specific implementation of
HashSet
orHashMap
used (the behaviour is Java version dependent, and possibly depended on patch level), and - for Java 8 and later, whether or not the keys are
Comparable
.
If you have all of that information (and you are prepared to emulate the insertion / removal sequence), you can accurately predict the iteration order. However, it would be tricky to implement, and expensive to run ...
In your example, the hash values are the same, the initial HashSet
capacity is the same, the insertion order is the same, and the HashSet
implementation is the same. In those circumstances (and given the precise algorithms used) the iteration order is going to repeatable ... even if though it would difficult to predict.
In this case, the order is not "random" because there is no randomness in the process that builds the HashSet
. Just calculations that are complicated and opaque ... but deterministic.
I have read in java 1.7 docs that "It makes no guarantees as to the iteration order of the set". what is meaning of this?
What is means is that the javadoc is not committing to any specific behaviour vis-a-vis the ordering. Certainly, there is no commitment to portable behaviour.
See also: Order of values retrieved from a HashMap
Why HashSet order always same for my program?
The reason for this behaviour is that a HashSet
is backed by a HashMap
, which in turn is backed by an array
of Entry
-objects. where the hash
is used to find the index
of the array
. So there is always an order of elements in a HashSet
(the order of the array
), you just don't have any guarantees as to what this order is.
As far as I can tell from the code, the order of the HashSet
is determined (or at least affected) by the order of the computed hashes
of its elements. Then, with relatively simple inputs (like your single character string), one might assume that there is a strict ordering of the hashes
, which will give you what seems to be a natural ordering. With more complex objects, and thus more complex hash
computations, the hashes
will be more spread, and the ordering "more random".
Also, like it's been pointed out, "no guarantee of ordering" does not imply "guaranteed random ordering".
The hashcode
-method of the String
class also comes into play here, for single character String
s the hashcode
will just be the int
value of the one char
in the String
. And since char
's int
values are ordered alphabetically, so will the computed hashes
of single char
String
s.
Java HashSet - is there a way to specify the order in which elements will be displayed?
You can Use LinkedHashSet
it keeps order of elements.
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). Note that insertion order is not affected if an element is re-inserted into the set. (An element e is reinserted into a set s if s.add(e) is invoked when s.contains(e) would return true immediately prior to the invocation.)
LinkedHashSet
Java Set retain order?
The Set
interface does not provide any ordering guarantees.
Its sub-interface SortedSet
represents a set that is sorted according to some criterion. In Java 6, there are two standard containers that implement SortedSet
. They are TreeSet
and ConcurrentSkipListSet
.
In addition to the SortedSet
interface, there is also the LinkedHashSet
class. It remembers the order in which the elements were inserted into the set, and returns its elements in that order.
Iteration order of HashSet
Absolutely not.
The insertion order directly influences the iteration order whenever you have a bucket collision:
When two elements end up in the same bucket, the first one that was inserted will also be the first one returned during iteration, at least if the implementation of collision handling and iteration is straightforward (and the one in Sun's java.util.HashMap
is)
Related Topics
Count Int Occurrences with Java8
Accessing Kotlin Extension Functions from Java
Process Thymeleaf Variable as HTML Code and Not Text
Hashcode and Equals for Hashset
Spring Boot Actuator Application Won't Start on Ubuntu Vps
How Does the Enhanced for Statement Work for Arrays, and How to Get an Iterator for an Array
How to Serialize an Object That Includes Bufferedimages
Why Does Hibernate Disable Insert Batching When Using an Identity Identifier Generator
Drag and Drop Custom Object from Jlist into Jlabel
Apache Httpclient Making Multipart Form Post
Java Swing Jtextfield Set Placeholder
Java: Global Exception Handler
How to Mix --Class-Path and --Module-Path in Javac (Jdk 9)
How to Run All Tests Belonging to a Certain Category in Junit 4