Set collection (HashSet collection)

Set collection: a collection that does not contain repeated elements. To be more precise, the set does not satisfy the element pair e1 and e2 of e1.equals(e2) and contains a null element. As the name implies, this interface mimics the mathematical set abstraction.

java.util.Set interface extends Collection interface

Features:

1. It is not allowed to store duplicate elements

2. There is no index, no method with index, and ordinary for loop traversal cannot be used.

一.HashSet

This class implements the Set interface and is supported by a hash table (actually a HashMap instance). It does not guarantee the iteration order of the set; in particular, it does not guarantee that the order will remain the same forever. This class allows the use of null elements.

This implementation is also not synchronous .

public static void main(String[] args) { 
    // polymorphic writing 
    Set<Integer> set = new HashSet<>(); 
    set.add(1); 
    set.add(3); // disorder, access The order is inconsistent 
    set.add(2); 
    set.add(1); // There can be no repeated elements 
    // You can not use ordinary for loops, you can iterate, you can also foreach loop 
    Iterator<Integer> iterator = set.iterator(); 
    while (iterator.hasNext()){ 
        System.out.println(iterator.next()); // 1 2 3 
    } 
    for (Integer i: set) { 
        System.out.println(i); // 1 2 3 
    } 
}

The structure of the hash set to store the data (hash table)

What is a hash table?

Let’s first look at the hash value (hash value)

Definition: It is a decimal integer, randomly given by the system (that is, the address value of the object, a logical address, the simulated address, not the physical address where the data is actually stored)

There is a method in the Object class to get the hash value of the object.

public native int hashCode(): Returns the hash value of the object .

native: It means that the method calls the method of the local operating system.

 

public static void main(String[] args) { 
    Person person = new Person(); 
    // The Person class inherits the Object class, so you can use the hashCode method of the Object class 
    int hash = person.hashCode(); 

    Person person1 = new Person (); 
    int hash1 = person1.hashCode(); 

    /*The toString method in the Object source code: 
    public String toString() { 
    return getClass().getName() + "@" + Integer.toHexString(hashCode());} 
    The second half of the output is the hexadecimal representation of the hash address value 
     */ 
    // Compare 
    System.out.println(person); // demo08.Person@1b6d3586 
    System.out.println(hash); // 460141958 
}

Note that in the toString method of Object source code, the second half of @ printed is the hexadecimal number of the hash address value.

But the same is just a logical address, not a physical address.

 

The same logical address does not mean the same physical address! The object is different, the hash address may also be the same.

For example:

 

System.out.println(person == person1); // false
String str = new String("aaa");
String str1 = new String("aaa");
System.out.println(str.hashCode()); // 96321
System.out.println(str1.hashCode()); // 96321
// The logical address is not the same as the physical address 
System.out.println(str == str1); // false 

// The object is different, and the hash address may be the same 
System.out.println("重地".hashCode( )); // 1179395 
System.out.println("Call".hashCode()); // 1179395

 

Before JDK1.8, the bottom layer of the hash table was implemented by array + linked list, that is, the linked list is used to handle conflicts, and the linked lists of the same hash value are stored in a linked list. But when there are many elements in a bucket, that is, when there are many elements with equal hash values, the efficiency of searching through the key value at one time is low. In JDK1.8, the hash table storage is realized by array + linked list + red-black tree. When the length of the linked list exceeds the threshold (8), the linked list is converted to a red-black tree, which greatly reduces the search time.

Simply put, the hash table is implemented by an array + linked list + red-black tree (JDK1.8 adds the red-black tree part).

As shown in the explanation:

 

Let's learn the principle that HashSet does not allow elements to be repeated:

// Create a HashSet collection 
HashSet<String> hashSet = new HashSet<>(); 
// Store elements 
String str1 = new String("aaa"); 
String str2 = new String("aaa"); 
hashSet.add(str1) ; 
hashSet.add(str2); 
hashSet.add("heavy ground"); 
hashSet.add("call"); 
hashSet.add("aaa"); 
System.out.println(hashSet); // [aaa, heavy ground , Call]

 

 

HashSet stores custom type elements

Store data of Integer and String types in HashSet. These data types are already defined types, and the hashCode method and equals method are overridden, so how to store custom type elements?

Also rewrite the hashCode method and equals method!

When storing custom type elements for HashSet, you need to rewrite the hashCode method and equals method in the object and establish your own comparison method to ensure that the objects in the HashSet collection are unique.

When there is no rewrite method:

public static void main(String[] args) { 
    // Create a HashSet collection to store Person 
    HashSet<Person> hashSet = new HashSet<>(); 

    Person p1 = new Person("易烊千玺"); 
    Person p2 = new Person ("王俊凯"); 
    Person p3 = new Person("易千玺"); hashSet.add(p1); 
    hashSet.add(p2); 
    hashSet.add(p3); 

    System.out.println(p1.hashCode ()); // 460141958 
    System.out.println(p3.hashCode()); // 1956725890 
    System.out.println(p1.equals(p3)); // false 
    // When the equals and hashCode methods are not overridden 
    // Print [Person{name='Yiyang Qianxi'}, Person{name='王俊凯'}, Person{name='Yiyang Qianxi'}] 
    // Unable to identify the same celebrity 
    System.out.println(hashSet ); 
}

After rewriting the method:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name);
}
System.out.println(p1.hashCode()); // 806906957
System.out.println(p3.hashCode()); // 806906957
System.out.println(p1.equals(p3)); // true

System.out.println(hashSet); // [Person{name='王俊凯'}, Person{name='易烊千玺'}]

 

Guess you like

Origin blog.csdn.net/wardo_l/article/details/113990846