### Why does My HashSet Sort?

# HashSet sorting phenomenon

Recently, in the knowledge of Set Collection, Set is a collection that does not save duplicate elements. The code below adds a number between 0 and 29 100 times, but the result of running intSet is only a number between 0 and 29.

import java.util.*; public class SetOfInteger { public static void main(String[] args) { Random random = new Random(47); Set<Integer> intSet = new HashSet<>(); for (int i = 0; i < 100; i++) { intSet.add(random.nextInt(30)); } System.out.println(intSet); } } /* output * [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29] **/

But the result of this output made me very curious. Why is there sorting, not HashSet?Maybe you should go deeper into the source code

# Source Code Analysis

We can find the add method inside the HashSet, which was originally done using HashMap, Key is the inserted number, and Value is an object of new.

//HashSet.java private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); public boolean add(E e) { return map.put(e, PRESENT)==null; }

Then comes HashMap's put method, and what really affects our sorting is the code below, where putVal passes in three hash,key,value.

This is the conjecture that our Integer hash is his value, and we can also find it clearly through the debug putVal function.

We know that hash actually affects the sorting problem. Finding the source code reveals that the hash value is determined by the key.hashCode() function.

That is, we return exclusive OR results for (h = key.hashCode()) and (h >>> 16)

//HashMap.java public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) { ...... } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }

# What is Integer's hash value?

The element we put in the HashSet above is Integer, and Integer's hashCode is his original value.We can find the hashCode() function in the Integer class

//Integer.java @Override public int hashCode() { return Integer.hashCode(value); } public static int hashCode(int value) { return value; }

h=key.hashCode() and h>>16 (the value of H moves 16 bits to the right) The XOR result is the original value for the number of sixteen powers less than two.

So the reason is analyzed

# extend

(h = key.hashCode()) ^ (h >>> 16)

The above code means: the H value equals the hashCode of the key, then right-shifts the binary of h by 16 bits, an Integer by 32 bits, then 0 is in front of the value less than 2^16=65536

Integer H = 1; //h equals 1 Binary of 0000 0000 0000 0000 0000 0000 0001 //h H >>> 16 //h Right shift 16 bits 0000 0000 0000 0000 0000 0000 0000 0000 //Right-shifted binary If exclusive to the original h or 0000 0000 0000 0000 0000 0000 0001//XOR results

There is another online statement that adds a value of 65536, which simply means that by adding a number whose binary number is greater than 16 digits, the right shift will change and a hash value will be generated that is not the same as before.(I haven't looked at how much this value should add) Chestnuts are below.

import java.util.*; public class SetOfInteger { public static void main(String[] args) { Random random = new Random(); Set<Integer> intSet = new HashSet<>(); for (int i = 0; i < 100; i++) { int a = random.nextInt(20); intSet.add(a + 65536*2*10); } Iterator it = intSet.iterator(); while (it.hasNext()) { Integer integer = (Integer) it.next(); System.out.print(integer-65536*2*10 + " "); } //System.out.println(intSet); } } /*output *16 17 18 19 4 5 6 7 0 1 2 3 12 13 14 15 8 9 10 11 */