「Java基礎」關於Set的子類,HashSet與TreeSet

2020-08-12 20:40:30

HashSet與TreeSet

Set是Collection的子介面,與它同級的介面還有List、Queue;

關於Set,它的顯著性特徵就是,無法記錄數據儲存的先後順序,無法儲存重複元素進入數據集合;

接下來介紹下HashSet與TreeSet

一、關於HashSet

1.hashset的儲存特點?

無序性、單元性

2. HashSet是如何做到不去記錄相同的元素呢?

通過了兩個判斷,第一個:通過HashCode;第二個:通過equals完成;

更近一步解釋的:
(1)當我們建立出了一個新的HashSets,向內傳入數據時,我們需要計算出HashCode值出來,計算方式我們可以自定義。

(2)將新傳入的數據計算出HashCode值,之後與集合內的每個進行比較,會出現兩種情況:

A:新HashCode值未出現,則直接將新值插入到集合。

B:新HashCode值出現過,則進行equals判斷,將新插入元素與已存在的元素進行equals判斷,這時也會出現兩種結果:

C:返回ture,兩個元素相同,則不會插入新值。

D:返回False,兩個元素雖然HashCode值相同,但是元素本身並不相同,選擇插入新元素。
import java.util.HashSet;
import java.util.Iterator;

class hashSetDemo
{
    public static void main(String[] args)
    {
        HashSet a = new HashSet();

        a.add(new Person("wangziyu01", 23));
        a.add(new Person("wangziyu01", 23));// 重複
        a.add(new Person("wangziyu02", 24));
        a.add(new Person("wangziyu03", 25));
        a.add(new Person("wangziyu04", 26));
        a.add(new Person("wangziyu04", 26));// 重複 hashset重複元素進行兩次判斷:hashCode值判斷+equals內容判斷
        Iterator it = a.iterator();
        while (it.hasNext())
        {
            Person p = (Person)it.next();
            sop(p.getName()+"..."+p.getAge());// 列印結果
        }
    }
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
}
class Person // 定義 equals比較方法 + hashCode計算方法
{
    private String name;
    private int age;
    Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    public boolean equals(Object obj)  //定義equals比較方法
    {
        if(!(obj instanceof Person))
            return false;
        Person p = (Person)obj;
        System.out.println(this.name+"..hashCode相同時,執行equals比較內容.."+p.name);
        return this.name.equals(p.name) && this.age == p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
    public int hashCode() {  //定義hashCode計算方法
        System.out.println(this.name + "....計算hashCode");
        return name.hashCode() + age * 37;
    }
}

最後列印出來的結果解釋:
wangziyu01…計算hashCode
wangziyu01…計算hashCode
wangziyu01…hashCode相同時,執行equals比較內容…wangziyu01 // equals比較結果相同,進行剔除
wangziyu02…計算hashCode
wangziyu03…計算hashCode
wangziyu04…計算hashCode
wangziyu04…計算hashCode
wangziyu04…hashCode相同時,執行equals比較內容…wangziyu04 // equals比較結果相同,進行剔除

最終結果:
wangziyu04…26
wangziyu01…23
wangziyu03…25
wangziyu02…24

3 HashSet總結:

(1)數據結構爲雜湊表,執行緒爲非同步

(2)保證元素唯一性的原理:判斷元素的hashCode值是否相同,如果相同,還會繼續判斷元素的equals方法,是否爲true。

(3)HashCode的計算方法與equals方法可以在物件中自定義,而不需要管如何呼叫,它是自動的

(4) HashSet數據集無法記錄儲存順序。

(5)HashSet數據集無法儲存相同元素。

二、關於TreeSet:

基本介紹:TreeSet是Set下子類,TreeSet會對傳入的數據進行排序。
TreeSet的底層數據爲二元樹結構,使用到了compareTo方法return 0;來保證元素的唯一性。

1. TreeSet排序前需要準備哪些? 需要怎麼指定排序方式?

需要讓數據具有可比性:
(1)方式一:讓元素自身具備比較性。

解釋:元素自身實現Compareable介面(例如:學生物件的數據,讓它實現可比性),之後覆蓋compareTo方法,在這個方法中指定返回值,比較無非三種情況:當新加入數據比較結果較大時,返回1;當新加入數據比較結果較小時,返回-1;相同時返回0;

下面 下麪是方式一的體現結果,讓Person具有可比性:

class TreeSetDemo
{
    public static void main(String[] args)
    {
        TreeSet ts = new TreeSet();

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi08",19));
        ts.add(new Student("lisi007",20)); // 重複元素
        //ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}


class Student implements Comparable//該介面強制讓學生具備比較性。
{
    private String name;
    private int age;

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

    public int compareTo(Object obj)
    {

        //return 0;

        if(!(obj instanceof Student))
            throw new RuntimeException("不是學生物件");
        Student s = (Student)obj;

        System.out.println(this.name+"....compareto....."+s.name);
        if(this.age>s.age)
            return 1;
        if(this.age==s.age)
        {
            return this.name.compareTo(s.name);
        }
        return 1;
        /**/
    }

    public String getName()
    {
        return name;

    }
    public int getAge()
    {
        return age;
    }
}

列印結果爲:
lisi02…compareto…lisi02
lisi007…compareto…lisi02 // 插入元素與集合已存在的進行比較
lisi09…compareto…lisi02
lisi09…compareto…lisi007
lisi08…compareto…lisi007
lisi08…compareto…lisi09
lisi007…compareto…lisi007 //查詢到了相同的元素準備插入,
lisi02…22
lisi007…20
lisi08…19
lisi09…19

(2)方式二:讓集合自身具備比較性。

解釋:當元素自身不具備比較性時,或者具備的比較性不是所需要的,在集合初始化時,就有了比較方式。