JavaSE基礎———Set接口中的常用類HashSet、LinkedHashSet和TreeSet

1. HashSet 集合

   (1)HashSet 的概述

     HashSet 的底層數據結構是哈希表(哈希表是一個元素爲鏈表的數組)。HashSet 不是線程安全的,集合元素可以是null。當向HashSet 中存入一個元素時,HashSet 會調用該對象的HashCode()方法來得到該對象的HashCode值,然後根據HashCode值決定該對象在HashSet 中的存儲位置。

   (2)HashSet判斷兩個元素相等的標準:

     兩個對象的HashCode值相等,並且兩個對象的equals方法的返回值也相等。

代碼演示:


import java.util.Objects;

public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

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

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
import java.util.HashSet;

public class Test {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();
        set.add(new Person("張三",21));
        set.add(new Person("張三",22));
        set.add(new Person("張三",21));
        System.out.println(set);
    }
}

執行結果:
在這裏插入圖片描述
重寫了HashCode和equals方法後才能保證對象元素的唯一性。

2. LinkedHashSet 集合

   (1)概述

      LinkedHashSet 是底層數據是鏈表和哈希表。鏈表保證了數據的有序性,哈希表保證了數據的唯一性。

   (2)特點:LinkedHashSet的存儲順序和取出的順序是一樣的,它是線程不安全的集合,運行速度快。

3. TreeSet 集合

   (1)概述

      TreeSet 集合繼承於AbstractSet,所以它是一個Set集合,具有Set的屬性和方法。
      TreeSet基於TreeMap實現的。TreeSet中含有一個”NavigableMap類型的成員變量”m,而m實際上是”TreeMap的實例”。 底層的數據結構是紅黑樹(平衡二叉樹)。

   (2)特點

     存入的元素唯一併且可以對元素排序。
     排序方式有兩種:自然排序和比較器排序。
     如果要使用自然排序,那麼對其中元素就要求實現Comparable 接口。

代碼演示:

package com.westos.demo;

import java.util.Objects;

public class Person implements Comparable<Person>{
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    public int compareTo(Person p) {
        int num  = this.age-p.age;
        int num2 = num==0?this.name.compareTo(p.name):num;
        return num2;
    }
}

package com.westos.demo;

import java.util.TreeSet;

public class Test1 {
    public static void main(String[] args) {
        TreeSet<Person> set = new TreeSet<>();
        set.add(new Person("張三",25));
        set.add(new Person("李四",21));
        set.add(new Person("王五",23));
        set.add(new Person("王五",28));
       for (Person person : set) {
            System.out.println(person);
        }
    }
}

不寫排序的異常:
在這裏插入圖片描述
執行結果:
在這裏插入圖片描述
4. HashCode和equals方法的面試題

   ● 問題: 如果兩個對象的哈希值相同 p1.hashCode()==p2.hashCode() , 兩個對象的equals一定返回true嗎 p1.equals(p2) 一定是true嗎?

   正確答案:不一定

   ● 如果兩個對象的equals方法返回的結果爲true,兩個對象的哈希值一定相同嗎?

   正確答案:一定

在 Java 應用程序執行期間,
1.如果根據 equals(Object) 方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用 hashCode 方法都必須生成相同的整數結果。
2.如果根據 equals(java.lang.Object) 方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不 要求一定生成不同的整數結果。

兩個對象不同(對象屬性值不同) equals返回false=====>兩個對象調用hashCode()方法哈希值相同

兩個對象調用hashCode()方法哈希值不同=====>equals返回true

所以說兩個對象哈希值無論相同還是不同,equals都可能返回true

發佈了56 篇原創文章 · 獲贊 5 · 訪問量 2126
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章