Set

破忒头头發表於2024-03-09

Set集合的特點

HashSet:無序;不重複;無索引
LinkedHashSet:有序;不重複;無索引
TreeSet:可排序(預設升序);不重複;無索引

HashSet

  • 基於雜湊表實現
  • 雜湊表是一種增刪改查資料,效能都比較好的資料結構

雜湊表:JDK8之前,雜湊表=陣列+連結串列 JDK8之後,雜湊表=陣列+連結串列+紅黑樹

JDK8之前

HashSet擴容

HashSet去重複問題

示例程式碼如下

import lombok.AllArgsConstructor;
import lombok.Data;

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

/**
 * @author Pickle
 * @version V1.0
 * @date 2024/3/9 13:57
 */

@AllArgsConstructor
class Student{
    private String name;
    private Integer age;
    private Double height;

    @Override
    public String toString() {
        return this.name + " " + this.age + " " + this.height;
    }
}
public class SetDemo {
    public static void main(String[] args) {
        Set<Student> set = new HashSet<>();
        set.add(new Student("小明",11,180.0));
        set.add(new Student("小明",11,180.0));
        set.add(new Student("小明",11,180.0));
        final Iterator<Student> iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

列印結果

Set集合中出現了三個一摸一樣的物件

解決方法,重寫Student的hashCode和equals方法,因為Student預設的equals繼承的Object方法對比的是記憶體地址,所以認為是三個不同的物件

重寫Student類的equals和hashCode方法問題解決

LinkedHashSet

  • LinkedHashSet依然是基於雜湊表(陣列,連結串列,紅黑樹)實現的
  • 但是,他的每個元素都額外的多了一個雙連結串列的機制記錄他前後元素的位置。

TreeSet

import com.sun.source.tree.Tree;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author Pickle
 * @version V1.0
 * @date 2024/3/9 14:57
 */
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        //底層是基於紅黑樹排序
        Set<Integer> set = new TreeSet<>();
        set.add(6);
        set.add(5);
        set.add(7);
        set.add(4);
        set.add(10);
        System.out.println(set);

    }
}

紅黑樹的插入過程


比如下面的程式碼

import com.sun.source.tree.Tree;
import lombok.AllArgsConstructor;

import java.util.*;

/**
 * @author Pickle
 * @version V1.0
 * @date 2024/3/9 14:57
 */
@AllArgsConstructor
class Student{
    private String name;
    private Integer age;
    private Double height;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        //這裡錯誤的比較,因為欄位都是引用型別的變數,下邊的程式碼一定是返回False的
        //return name==student.name &&age==student.age&& height==student.height;
        return Objects.equals(name,student.name) && Objects.equals(height, student.height)&&Objects.equals(age,student.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, height);
    }

    @Override
    public String toString() {
        return this.name + " " + this.age + " " + this.height;
    }
}
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        //底層是基於紅黑樹排序
        Student s1 = new Student("A",11,180.0);
        Student s2 = new Student("B",12,180.0);
        Student s3 = new Student("C",13,180.0);
        Set<Student> set = new TreeSet<>();
        set.add(s1);
        set.add(s2);
        set.add(s3);
        System.out.println(set);

    }
}

直接報錯,原因是他不知道Student應該怎麼排序,所以應該實現Comparable介面重寫compare方法