Java collection -- Set interface and its implementation classes HashSet, LinkedHashSet and TreeSet

Set Interface Overview

1. The set interface is a sub interface of the Collection. The set interface does not define additional methods, but uses the methods in the Collection interface.
2. The Set set cannot contain the same elements. If you try to add two identical elements to the same Set set, the add operation fails.


3. Set: stores unordered and non repeatable data
(take HashSet as an example)
① Disorder: not equal to randomness. The stored data is not added in the order of the array index in the underlying array, but according to the hash value of the data.
② Non repeatability: ensure that the added element cannot return true when judged according to equals(). That is, only one element can be added to the same element.

HashSet implementation class

1. HashSet has the following characteristics:
① The order of elements cannot be guaranteed
② HashSet is not thread safe
③ Collection elements can be null

2. HashSet sets the criteria for judging the equality of two elements: the two objects are equal through hashCode() method, and the return values of the equals() method of the two objects are also equal. Therefore, for objects stored in the Set container, the corresponding class must override the equals() and hashCode() methods to implement the object equality rule, that is, "equal objects must have equal hash codes".

3. To add an element to a HashSet:
We add element a to the HashSet. First, we call the hashCode() method of the class where element a is located to calculate the hash value of element a, and then calculate the storage position (index position) in the underlying array of the HashSet through some algorithm. Then judge whether there are elements in this position of the array:

If there are no other elements at this location, element a is added successfully. > Case 1
If there are other elements b in this position (or there are multiple elements in the form of a linked list), compare the hash values of element a and element b:

If the hash values are different, element a is added successfully. > Case 2
If the hash values are the same, you need to call the equals() method of the class where element a is located:

If equals() returns true, element a addition fails
If equals() returns false, element a is added successfully. > Case 3

For cases 2 and 3 where the addition is successful, element a and the data already existing at the specified index position are stored in a linked list. (seven up and eight down)
jdk 7: the new element a is placed in the array and points to the existing old element.
jdk 8: the existing old element is in the array, pointing to the new element a


The bottom layer is "array + linked list". The initial capacity of the array is 16. If the utilization rate exceeds 0.75 (16 * 0.75 = 12), the capacity will be doubled. (16 capacity expansion is 32, followed by 64128...)

When rewriting the equals() method, you generally need to duplicate the hashCode() method at the same time. Generally, the properties of the objects involved in the hash value calculation should also be involved in the equals() calculation

LinkedHashSet implementation class

1. LinkedHashSet is a subclass of HashSet. It also determines the storage location of elements according to the hashCode value of elements. However, it also uses a two-way linked list to maintain the order of elements, which makes the elements appear to be saved in insertion order.

2. The insertion performance of LinkedHashSet is slightly lower than that of HashSet, but it has good performance when iteratively accessing (traversing) the elements in the Set.

3. LinkedHashSet does not allow duplicate collection elements.

TreeSet implementation class

1. TreeSet is the implementation class of SortedSet interface. TreeSet can ensure that the collection elements are in sorting state. Element should be an object of the same class.

2. The underlying TreeSet uses a red black tree structure to store data.

3. TreeSet has two sorting methods: natural sorting and custom sorting. By default, TreeSet adopts natural sorting.

4. Natural sorting
① TreeSet will call the compareTo(Object obj) method of collection elements to compare the size relationship between elements, and then arrange the collection elements according to conditions. If you try to add an object to a TreeSet, the object's class must implement the Comparable interface. The class implementing Comparable must override the compareTo(Object obj) method. The two objects are compared in size through the return value of the compareTo(Object obj) method.
② When adding elements to TreeSet, only the first element does not need to compare the compareTo() method, and the following element is added
All elements added will call the compareTo() method for comparison.
③ Because only two instances of the same class will be compared in size, the same class should be added to TreeSet
An object of a class.
④ For the TreeSet set, the only criterion for judging whether two objects are equal is the return value of the two objects compared through the compareTo(Object obj) method.

import java.util.Iterator;
import java.util.TreeSet;

/**
 * @Author: Yeman
 * @Date: 2021-09-16-16:48
 * @Description:
 */

class Student implements Comparable{
    String name;
    int age;

    public Student() {
    }

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

    @Override
    //Name from small to large, age from large to small
    public int compareTo(Object o) {
        if (o instanceof Student){
            Student student = (Student) o;
            int nameResult = this.name.compareTo(student.name);
            if (nameResult == 0){
                return -Integer.compare(this.age,student.age);
            }else {
                return nameResult;
            }
        }else throw new RuntimeException("type mismatch");
    }

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

public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet();
        treeSet.add(new Student("Tom",18));
        treeSet.add(new Student("Tom",22));
        treeSet.add(new Student("jim",18));
        treeSet.add(new Student("Anne",19));
        treeSet.add(new Student("Lily",25));
        treeSet.add(new Student("LiLei",25));

        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}


5. Custom sorting
① Custom sorting is implemented through the Comparator interface, and the compare(T o1,T o2) method needs to be rewritten.
② To implement custom sorting, you need to pass an instance that implements the Comparator interface as a formal parameter to the constructor of TreeSet.
③ Still, only objects of the same type can be added to TreeSet. Otherwise, a ClassCastException exception occurs.
④ The criterion for judging the equality of two elements using custom sorting is that the Comparator returns 0 when comparing two elements.

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
 * @Author: Yeman
 * @Date: 2021-09-16-16:48
 * @Description:
 */

class Student{
    String name;
    int age;

    public Student() {
    }

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

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

public class TreeSetTest {
    public static void main(String[] args) {
        Comparator com = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if (o1 instanceof Student && o2 instanceof Student) {
                    Student student1 = (Student) o1;
                    Student student2 = (Student) o2;
                    return Integer.compare(student1.age, student2.age);
                } else throw new RuntimeException("type mismatch");
            }
        };
        TreeSet treeSet = new TreeSet(com);
        treeSet.add(new Student("Tom",18));
        treeSet.add(new Student("Tom",22));
        treeSet.add(new Student("jim",18));
        treeSet.add(new Student("Anne",19));
        treeSet.add(new Student("Lily",25));
        treeSet.add(new Student("LiLei",25));

        Iterator iterator = treeSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

Tags: Java set HashSet Collection

Posted on Thu, 16 Sep 2021 21:05:26 -0400 by spfoonnewb