Duplicate values of the HashSet class and TreeSet class corresponding to the Set collection

Regarding the HashSet class, this is a question I had after reading an official code writing method when I was brushing leetcode. I couldn’t find the answer on the Internet, and finally found the answer in the API:

Why can’t I find the answer online? What was shown was that HasSet cannot store duplicate elements (perhaps there is something wrong with my understanding). The more I read, the more confused I became. Finally, I suddenly thought of looking at the API to find the correct solution! —–>> Address != value (content), below we use “content” instead of the “value” we often say! ! ! !

The duplicate value here in HashSet does not refer to two variables with “the same content”, but whether the “address” of the two variables points to the same block. The one with the same address is the “duplicate value”. However, among the basic data types such as int, double, float, etc., the “same content” of these types will point to the same address, but different objects instantiated (new) by the custom class will point to different addresses, although “The content is the same”, but it will not be judged as a duplicate value in the HashSet class. It will be clearer by looking at the following code.

The basic data type is int as an example:

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

Scanner sc =new Scanner(System.in);
int a = 3;
int b = 3;
System.out.println("Integer type: ");
System.out.println("The address of a: " + System.identityHashCode(a));
System.out.println("b's address: " + System.identityHashCode(b));
\t\t
Set<Integer> intSet = new HashSet<Integer>();
System.out.print("Input value: ");
for(int i=0; i<5; i + + ){
intSet.add(sc.nextInt());
}
Iterator<Integer> intIt = intSet.iterator();
while(intIt.hasNext()){
System.out.print(intIt.next() + " ");
}
\t\t
sc.close();
\t  
}
}

operation result:

The “same content” of basic data types such as int points to the same address, and the “same content” has been removed.

String is a reference type. If you directly assign “the same string” to different variables, the addresses they point to are the same, but different variables created with “same content” new String() will point to different addresses, and custom The class is like new String(), which instantiates (new) “the same content” to different variables, and the addresses they point to are different.

In general, every new object will open up a unique address for the corresponding variable.

Look at the following code example:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;

//Custom class
class ListNode {
     int val;
     ListNode(int x) {
         val = x;
     }
 }

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

Scanner sc =new Scanner(System.in);
//new String type
System.out.println("new String type: ");
String sk = new String("kkk");
String sg = new String("kkk");
System.out.println("sk's address: " + System.identityHashCode(sk));
System.out.println("sg's address: " + System.identityHashCode(sg));
\t\t
//Assign string directly
String s1 ="kkk" ;
String s2 ="kkk" ;
System.out.println("String type: ");
//Output the addresses of variables s1 and s2 respectively
System.out.println("Address of s1: " + System.identityHashCode(s1));
System.out.println("Address of s2: " + System.identityHashCode(s2));
\t\t
//Create HashSet table
Set<String> strSet = new HashSet<String>();
\t\t
//Input value verification
for(int i=0; i<5; i + + ){
strSet.add(sc.next());
}
\t\t
//HashSet iterator---output
Iterator<String> str = strSet.iterator();
while(str.hasNext()){
System.out.print(str.next() + " ");
}
\t\t
\t\t
System.out.println();
System.out.println("-----------------------------------------") ;
System.out.println();
\t\t
// Custom class ListNode
ListNode n1 = new ListNode(1);
ListNode n2 = new ListNode(1);
System.out.println("Custom class ListNode:");
//Output n1,n2 address
System.out.println("n1= " + n1 + " Address of n1: " + System.identityHashCode(n1));
System.out.println("n2= " + n2 + " Address of n2: " + System.identityHashCode(n2));
\t\t
//Create HashSet table
Set<ListNode> nSet = new HashSet<ListNode>();
\t\t
//Enter any number of values to verify
for(int i=0; i<5; i + + ){
nSet.add(new ListNode(sc.nextInt()));
}
\t\t
//HashSet iterator---output
Iterator<ListNode> nd = nSet.iterator();
while(nd.hasNext()){
System.out.print(nd.next().val + " ");
}
\t\t
sc.close();
}
}

operation result:

By comparing the running results, it must be very intuitive. Different variables of new String() with “same content” point to different addresses. There is no list demonstration here (similar to the ListNode class below). You can try it yourself. The direct assignment of String “same content” will point to the same address, so it will be removed. However, although the custom ListNode class has “the same content”, they point to different addresses, so they will not be removed as “duplicate content”. .

In addition, the HashSet class does not guarantee the order of elements. If the order of elements is required, this does not apply.

The TreeSet class is more straightforward. The repeated values it refers to are “same content” and have nothing to do with data type or address.

Code example below:

import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;


//Custom classes need to implement the Comparable<> interface to use the TreeSet class, otherwise an error will be reported during operation.
class ListNode implements Comparable<ListNode>{
     int val;
     ListNode(int x) {
         val = x;
     }
@Override
public int compareTo(ListNode arg) {
// TODO Auto-generated method stub
if(this.val > arg.val)
return 1;
else if(this.val < arg.val)
return -1 ;
else
return 0;
}
     
     
 }

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

Scanner sc =new Scanner(System.in);
\t\t
//Implement the int type TreeSet class
Set<Integer> intSet = new TreeSet<Integer>();
System.out.println("int type:");
for(int i=0; i<6; i + + ){
intSet.add(sc.nextInt());
}
for(int y: intSet){
System.out.print(y + " ");
}
\t\t
\t\t
System.out.println();
System.out.println();
System.out.println();
\t\t
\t\t
\t\t
//Implement the custom type TreeSet class
Set<ListNode> nSet = new TreeSet<ListNode>();
System.out.println("Custom type:");
for(int j=0; j<6; j + + ){
nSet.add(new ListNode(sc.nextInt()));
}
for(ListNode x: nSet){
System.out.print(x.val + " ");
}
sc.close();
}
}

operation result:

It can be seen from the running results that the TreeSet class will remove the “same content”, which is what we usually call “numeric values”, and finally output it in ascending order.