JAVA中關於”容器“的理解

衆所周知,JAVA是一門強類型的編程語言,該語言有很多的特性,而本文所要講的是關於JAVA中“容器”這一知識點的簡要探究。在我看來,“容器”其實就是一種用來存儲數據的數據結構,在JAVA中容器可分爲即“集合”(Set)、“列表”(List)、“映射”(Map)。至於,爲什麼需要容器,總的來說,主要是在以數組作爲數據的存儲結構中,其長度難以擴充,同時數組中元素類型必須相同。而容器可以彌補數組的這兩個缺陷。下圖爲容器API類的一個結構圖。
這裏寫圖片描述
LinkedList相當於《數據結構》中線性結構中的鏈式存儲結構,ArrayList相當於順序存儲結構,它們分別實現了Set接口和List接口,而這兩個接口又分別實現了Collection接口,這個Collection接口中其實沒有任何方法和屬性,它只是起到一種標識的作用;HashMap也是一種容器,它現實了Map接口,其特點就是以鍵值對的形式來存放數據,它可以不用通過比較而直接進行數據的操作,可以比較好的解決”哈希衝突“問題,可是它並不能完美地解決該問題。但我要講的是關於HashSet這個子類使用方法的理解,如能理解這一問題,將會對JAVA中容器的概念有比較深刻的瞭解。
我們知道,在JAVA中合集的元素要求不重複,但可以無序,當我們往一個HashSet中添加數據的時候,如果沒有這個數據對象所屬的類沒有重寫相關方法,我們添加相同數據時,然後再輸出,就會發現,輸出了相同的數據,這很明顯和JAVA中集合的性制不符合。我們先來考慮一下,以下程序的運行結果。

public class TestHashSet

{
public static void main(String[] args)
{
Collection c = new HashSet();
c.add(new Student(1001, "張三"));
c.add(new Student(1002, "李四"));
c.add(new Student(1003, "王五")); //10行
c.add(new Student(1003, "王五"));
c.add(new Student(1003, "王五"));
c.add(new Student(1003, "王五"));
c.add(new Student(1003, "王五")); //14行


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


class Student
{
private int num;
private String name;


public Student()
{
}


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


public String toString()
{
return "學號: " + this.num + ",  姓名: " + name;
}

public boolean equals(Object o)//需要重寫的方法
{
Student s = (Student)o;

return this.num==s.num && this.name.equals(s.name);
}


public int hashCode()//需要重寫的方法
{

return num * this.name.hashCode();
}
}

當 hashCode()和equals(Object o)方法被重寫時,可以正常輸出集合中的數據,即它會自動把我們輸入的重複數據忽略。運行結果如下:
這裏寫圖片描述
但當我們把其中一個該重寫的方法註釋或兩個都註釋後。運行結果如下:
這裏寫圖片描述
我們可以發現輸入的重複數據全部輸出了,這明顯是不正確的。

這時,我們就應該考慮了,爲什麼要重寫這兩個方法,同時又應該怎樣去重寫?這兩個問題對深刻理解該容器的特性有很大的作用。
根據我的理解,我們首先要對《數據結構》有一定了解才行。
我可以理解爲的HashSet容器中的存儲結構應該是以鏈表的方式來存儲,而每個數據元素是根據一定計算放在不同或相同鏈表的不同位置。不同的鏈表又存在數組的不同位置。該存儲結構如下圖所示:
這裏寫圖片描述
在這之前,我們首先要了解的是,如果一個類沒有重寫hashCode方法,默認情況下,它會返回不同的值,即,當通過這個類來創建不同的對象時,所得到的hashCode值是不同的,還有一點就是,如果沒有重寫equals方法默認情況下,在比較一個類中的兩個 對象時,就算這兩個對象中的內容相等,也會返回false值。
還有一點需要注意的是通過java中的一些內置類已經重寫了hashCode()方法,因此通過這些類創建的對象其hashCode值是一樣的,equals方法也是被重寫了(即兩個對象的內容相等就返回true),而我們自己定義的類默認是沒有重寫的。
下面說一下。在執行一個元素的保存操作時,它的存儲過程其實是分爲兩個步驟的。第一步爲:通過hashCode()方法,計算一個類對應的hashCode值,要知道如果我們重寫了該方法,通過這個類創建的每個對象其hashCode值都是相同的,因此就可以唯一確定該對象應該存在哪個鏈表中,第二步是:當找到一個鏈表後,就要計算重寫的equals方法在鏈表中找一下,有沒有元素其內容已經和待存儲的元素內容相同,如果有就不存儲該,如果沒有,就把該元素放到該鏈表中。
由此我們可以看,爲什麼要重寫一個類中的這兩個方法了,
num * this.name.hashCode()就是要確保,通過該類創建的對象都有一個相同的hash碼值,以便存在相同的鏈表中;this.num==s.num && this.name.equals(s.name);功能就是比較兩個對象中的內容,如果內容相同則第二個對象就不用存儲了,這就保證在一個HashSet容器中不會出現相同的值對象。
以上就是關於hash“容器”的一個簡單小結。

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