The way of Java learning - Set interface, HashSet interface implementation class (important)

Keywords: Java Algorithm data structure

Work hard and see you at the top! come on.

1, Set interface

1. Introduction to set interface

  1. Out of order (the order of addition and extraction is inconsistent) and there is no index
  2. Duplicate elements are not allowed and contain at most one null

2. Traversal mode

  1. iterator
  2. Enhanced for loop (the underlying is also an iterator)
  3. Cannot get by index (i.e. no get method)

3. Common methods

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

public class Set01 {
    public static void main(String[] args) {
        //Use the HashSet subclass to demonstrate the use of the Set class
        Set set=new HashSet();
        set.add("john");
        set.add("lucy");
        set.add("john");
        set.add("jack");
        set.add(null);
        set.add(null);
        System.out.println(set);//[null, john, lucy, jack]
        // The object of the Set interface implementation class cannot store duplicate elements
        // The stored data is out of order
        // The order of the added elements is inconsistent with the order of the extracted elements (the order of the extracted elements is certain, and the underlying algorithm is used for sorting)

        //Iterator traversal
        Iterator iterator=set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //Enhanced for loop traversal
        for (Object o :set) {
            System.out.println(o);
        }

        //Delete element
        set.remove(null);
        System.out.println(set);

    }
}

2, HashSet interface implementation class

The underlying code of HashSet is more important. Review teacher Han Shunping's 522 ~ 525 lessons

https://www.bilibili.com/video/BV1fh411y7R8?p=521

hash()+equals()

  1. The bottom layer of HashSet is HashMap
  2. When adding an element, first get a hash value – > and convert it to an index value. HashSet first compares the hash value. The hash value of different objects is different. Even if the data stored in it is the same, it will be added to the array. (by default, except when the hashCode method is overridden).
  3. Find the storage data table table and see if the element has been stored in the index position
  4. If not, join directly
  5. If yes, call equals for comparison. If it is the same, discard the addition. If it is different, add it to the end
  6. In JDK8, if the number of elements in a linked list exceeds TREEIFY_THRESHOLD (8 by default), and table size > = min_ TREEIFY_ Capability (64 by default) will be converted into a red black tree.
  7. Hash value is not HashCode
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
        HashMap.Node[] tab;//HashMap is used
        int n;
        if ((tab = this.table) == null || (n = tab.length) == 0) {//table is a member variable of HashMap
            n = (tab = this.resize()).length;
        }

        Object p;
        int i;
        if ((p = tab[i = n - 1 & hash]) == null) {
            tab[i] = this.newNode(hash, key, value, (HashMap.Node)null);
        } else {
            Object e;
            Object k;
            if (((HashMap.Node)p).hash == hash && ((k = ((HashMap.Node)p).key) == key || key != null && key.equals(k))) {
                e = p;
            } else if (p instanceof HashMap.TreeNode) {
                e = ((HashMap.TreeNode)p).putTreeVal(this, tab, hash, key, value);
            } else {
                int binCount = 0;

                while(true) {
                    if ((e = ((HashMap.Node)p).next) == null) {
                        ((HashMap.Node)p).next = this.newNode(hash, key, value, (HashMap.Node)null);
                        if (binCount >= 7) {
                            this.treeifyBin(tab, hash);
                        }
                        break;
                    }

                    if (((HashMap.Node)e).hash == hash && ((k = ((HashMap.Node)e).key) == key || key != null && key.equals(k))) {
                        break;
                    }

                    p = e;
                    ++binCount;
                }
            }

            if (e != null) {
                V oldValue = ((HashMap.Node)e).value;
                if (!onlyIfAbsent || oldValue == null) {
                    ((HashMap.Node)e).value = value;
                }

                this.afterNodeAccess((HashMap.Node)e);
                return oldValue;
            }
        }

        ++this.modCount;
        if (++this.size > this.threshold) {
            this.resize();
        }

        this.afterNodeInsertion(evict);
        return null;
    }

Capacity expansion mechanism of HashSet

  1. The bottom layer of HashSet is HashMap. When adding for the first time, the table array is expanded to 16, the threshold is 16, and the loading factor LoadFactor is 0.75
  2. If the table array uses the critical value of 12, it will expand to 162 = 32, and the new critical value is 320.75 = 24, and so on.
    For example:
    Add the table array for the first time and expand it to 16. Continue to add.
    When 12 elements are added, the array is expanded again to 32 times the capacity of 16.
    When 32 is added × After 0.75 = 24 elements, the array is expanded again to twice 32 64.
    When 64 is added × After 0.75 = 48 elements, the array is expanded again to double the capacity of 64 128.
    And so on
    Note: as long as you add elements to the array, no matter which linked list you add, you add elements.
  3. In JDK8, if the number of elements in a linked list exceeds TREEIFY_THRESHOLD (8 by default), and table size > = min_ TREEIFY_ Capability (64 by default) will be transformed into a red black tree. Otherwise, the array capacity expansion mechanism will still be adopted (the number of elements is greater than 8, and the size of the table is greater than 64 = = > red black tree).

Commissioning procedure:

import java.util.HashSet;

public class HashSetlncrement {
    public static void main(String[] args) {
        HashSet hashSet=new HashSet();
        for (int i = 0; i < 100; i++) {
            hashSet.add(new A(i));
        }
    }
}

class A{
    private int n;
    public A(int n){
        this.n=n;
    }

    @Override
    public int hashCode() {
        return 100;
    }
}

3, HashSet exercise

1. Exercise 1

Define a class that includes: private member attribute name, age. requirement:

  1. Create three Employee objects and put them into the HashSet
  2. When the values of name and age are the same, they are considered to be the same employees and cannot be added to the HashSet.
import java.util.HashSet;
import java.util.Objects;

public class HashSetHomework {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add(new Employee("jack",18));
        hashSet.add(new Employee("tom",20));
        hashSet.add(new Employee("jack",18));

        System.out.println(hashSet);
    }
}
class Employee{
    String name;
    int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Employee)) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {//name and age are the same, and the same result is returned when hashCode is calculated
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Note: the hashCode and equals methods should be rewritten at the same time to realize the function of not adding repeatedly.

2. Exercise 2

Define an Employee class, which includes: private member attributes name, money, birthday (MyDate type), where MyDate types include year, month and day. requirement:

  1. Create three employees and put them into the HashSet.
  2. When the values of name and birthday are the same, they are considered to be the same employees and cannot be added to the HashSet set.

Posted by bnownlater on Fri, 24 Sep 2021 08:13:08 -0700