1. 程式人生 > >Java學習(set接口、HashSet集合)

Java學習(set接口、HashSet集合)

不重復 輸出 新元素 code TE pan tro int @override

一、set接口

概念:set接口繼承自Collection接口,與List接口不同的是,set接口所儲存的元素是不重復的。

二、HashSet集合

概念:是set接口的實現類,由哈希表支持(實際上是一個HashMap集合)。HashSet集合元素的提取順序與存儲順序不相同

   采用哈希表數據結構存儲數據,保證元素唯一性的方式依賴於:hashCode()與equals()方法

2.1哈希表

  什麽是哈希表? 鏈表與數組的組合

  哈希表底層使用的也是數組機制,數組中也存放對象,而這些對象往數組中存放時的位置比較特殊,當需要把這些對象給數組中存放時

那麽會根據這些對象的特有數據結合相應的算法

計算出這個對象在數組中的位置,然後把這個對象存放在數組中。而這樣的數組就稱為哈希數組即就是哈希表

  當向哈希表中存放元素時,需要根據元素的特有數據結合相應的算法,這個算法其實就是Object類中的hashCode方法。由於任何對象都是Object類的子類,所以任何對象有擁有這個方法。即就是在給哈希表中存放對象時,會調用對象的hashCode方法算出對象在表中的存放位置,這裏需要註意,如果兩個對象hashCode方法算出結果一樣,這樣現象稱為哈希沖突,這時會調用對象的equals方法比較這兩個對象是不是同一個對象,如果equals方法返回的是true,那麽就不會把第二個對象存放在哈希表中,如果

返回的是false就會把這個值存放在哈希表中。

  總結:保證HashSet集合元素的唯一,其實就是根據對象的hashCode和equals方法來決定的。如果我們往集合中存放自定義的對象,那麽保證其唯一,就必須復寫hashCode和equals方法建立屬於當前對象的比較方式。

  Hashcode方法用來計算哈希值。

hashCode方法計算圖:

技術分享圖片

哈希表數組和鏈表的結合圖

技術分享圖片

2.2HashSet存儲JavaAPI中的類型元素

給HashSet中存儲JavaAPI中提供的類型元素時,不需要重寫元素的hashCode和equals方法因為這兩個方法,在JavaAPI的每個類中已經重寫完畢

,如String類、Integer類等。

練習實例:

1.向哈希表添加元素並且打印

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;

public class Demo01 {
    //哈希表
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        method1();
     method2();
     method3();
     method4();
}
public static void method1(){ HashSet<String> set=new HashSet<String> (); set.add("abc"); set.add("abc"); set.add("ghi"); System.out.println(set); // }

打印結果:因為唯一性,所以只存儲了一個“abc”.

技術分享圖片

2.打印哈希值

//hashcode 方法(object類中提供)
    public static void method2(){
        String s1=new String("abc");
        String s2=new String("abc");
        //運行出來的 叫哈希值    運行的hashcode是string類的
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }

打印結果:哈希值 hashCode()

技術分享圖片

3.向哈希表中添加自定義類的元素並打印

自定義Person類:

public class Person {
    private String name;
    private int age;
    public Person(){
        
    }
    //重載構造方法,創建時賦值
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    
    @Override
    //轉為字符串
    public String toString() {
        return "Person [name=" + name + ", 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
    //重寫hashCode()方法
    public int hashCode() {
        
        return name.hashCode()+age*31;
    }
    @Override
    //重寫equals()方法
    public boolean equals(Object obj) {
        if(this==obj){
            return true;
        }
        if(obj==null){
            return false;
        }
        if(obj instanceof Person){
            Person p=(Person) obj;
            return name.equals(p.name)&&age==p.age;
        }
        return false;
    }
}

測試類方法:

public static void method3(){
        HashSet<Person> set=new HashSet<Person>();
        set.add(new Person("a",20));
        set.add(new Person("a",10));
        set.add(new Person("b",30));
        set.add(new Person("b",30));
        System.out.println(set);
    }

運行結果:因為重寫了hashCode方法跟equals方法 所以重復的元素並沒有存儲到集合中

技術分享圖片

三、LinkedHashSet集合:

我們知道HashSet保證元素唯一,可是元素存放進去是沒有順序的,那麽我們要保證有序,怎麽辦呢?

在HashSet下面有一個子類LinkedHashSet,它是鏈表和哈希表組合的一個數據存儲結構。

實例:叠代器遍歷有序唯一輸出:

//叠代器遍歷有序唯一輸出
    public static void method4(){
        LinkedHashSet<String> set=new LinkedHashSet <String>();
        set.add("a");
        set.add("aabbb");
        set.add("張三");
        set.add("李四");
        set.add("a");
        set.add("李四");
        Iterator it=set.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }        
    

運行結果:按照存儲順序打印

技術分享圖片

四、 判斷集合元素唯一的原理

4.1ArrayListcontains方法判斷元素是否重復原理

技術分享圖片

ArrayList的contains方法會使用調用方法時,傳入的元素的equals方法依次與集合中的舊元素所比較,從而根據返回的布爾值判斷是否有重復元素

true則有,false則無)。此時,ArrayList存放自定義類型時,由於自定義類型在未重寫equals方法前,判斷是否重復的依據是地址值,

所以如果想根據內容判斷是否為重復元素,需要重寫元素的equals方法

4.2HashSetadd/contains等方法判斷元素是否重復原理

技術分享圖片

Set集合不能存放重復元素,其添加方法在添加時會判斷是否有重復元素,有重復不添加,沒重復則添加。

HashSet集合由於是無序的,其判斷唯一的依據是元素類型的hashCode與equals方法的返回結果。規則如下:

先判斷新元素與集合內已經有的舊元素的HashCode值

l 如果不同,說明是不同元素,添加到集合。

l 如果相同,再判斷equals比較結果。返回true則相同元素;返回false則不同元素,添加到集合。

所以,使用HashSet存儲自定義類型,如果沒有重寫該類的hashCode與equals方法,則判斷重復時,使用的是地址值,如果想通過內容比較元素是否相同,

需要重寫該元素類的hashcode與equals方法

Java學習(set接口、HashSet集合)