Java集合學習之Collection(2)

來源:互聯網
上載者:User

標籤:set   hashset   treeset   linkedhash   

上篇部落格講了Collection介面的一些基本操作,這篇部落客要介紹Collection介面的子介面Set。
Set是一種無序的集合,其基本操作和Collection介面是差不多的,主要的不同點在於Set中不能重複元素而Collection集合是可以的。對於Set集合我們主要關心它的HashSet,TreeSet兩個實作類別。

一.HashSet
HashSet是Set介面的典型實現,大多數時候使用Set集合時就是使用這個類;HashSet通過hash演算法確定元素的儲存位置。值得注意的是HashSet中可以儲存值為null的元素。
那麼HashSet是怎樣工作的呢?我們每傳入一個元素,HashSet就調用該對象的HashCode()方法計算得到該對象的HashCode值,然後就根據這個值決定該元素在HashSet中的儲存位置。如果兩個對象通過equals()比較相等,但是計算出的HashCode值不相同,那麼HashSet就將他們儲存到不同的位置上去;如果兩個對象的HashCode值相等,而通過equals()方法比較不相等,那麼HashSet就將他們在同一個位置上以鏈表的形式儲存。
綜上我們可以知道HashSet判斷兩個對象相等的標準是:兩個對象的HashCode值相同,並且兩個對象通過equals()方法比較返回true。所以這兩個方法對HashSet來說是十分重要的,我們需要保證當兩個對象的HashCode值一樣時,其通過equals()方法比較也會返回true。下面的程式中A,B,C類分別重寫了自己的HashCode()和equals()方法。

public class A {    ///重寫A類的equals()方法,使其總是返回true    public boolean equals(Object obj){        return true;    }}public class B {    ///重寫B類的HashCode()方法,使其總是返回2    public int hashCode(){        return 2;    }}public class C {    ///重寫C類的equals()方法,使其總是返回true    public boolean equals(Object obj){        return true;    }    ///重寫C類的HashCode()方法,使其總是返回3    public int hashCode(){        return 3;    }}public class HashCodeTest {    public static void main(String[] args){        HashSet st = new HashSet();        //依次添加兩個A,B,C類對象        st.add(new A());         st.add(new A());        st.add(new B());        st.add(new B());        st.add(new C());        st.add(new C());        //可以看到只輸出了一個C類,而A,B類都輸出了兩個        System.out.println(st);    }}

HashSet有一個叫LinkedHashSet的子類,LinkedHashSet的基本原理和HashSet是一樣的,只是LinkedHashSet內部通過一個鏈表來維護插入元素的相對順序,這樣使得看起來元素是以插入的順序儲存的;當我們遍曆LinkedHashSet時就可以將元素以其輸入順序輸出了。

package lkl;import java.util.LinkedHashSet;public class LinkedHashSetTest {    public static void main(String[] args){        LinkedHashSet lt = new LinkedHashSet();        lt.add("java");        lt.add("c");        lt.add("c++");        lt.add("shell");        ///從下面兩次輸出可以看出,元素總是以輸入順序輸出        System.out.println(lt);        lt.remove("java");        lt.add("java");  ///從新添加後java被放到最後        System.out.println(lt);    }}

二.TreeSet
TreeSet是Set的另一個重要的子類。與HashSet通過hash的方式確定元素的儲存位置不同,TreeSet內部通過一棵紅/黑樹狀結構來維護元素的相對次序;由於TreeSet中元素的有序性,相對HashSet,還提供了幾個額外的方法,如下面的代碼所示:

package lkl;import java.util.TreeSet;public class TreeSetTest {public static void main(String[] args){    TreeSet ts = new TreeSet();    ts.add(1);    ts.add(-2);    ts.add(7);    ts.add(4);    ///從下面的輸出可以看出TreeSet是有序的    System.out.println(ts);    ///Comparator comparator()    ///如果TreeSet採用了定製排序,則返回定製排序的Comparator    ///如果採用了自然排序,則返回null    System.out.println(ts.comparator());    ///Object first():返回集合中第一個元素    ///Object last():返回集合中最後一個元素    System.out.println("集合中第一個元素為: "+ts.first());    System.out.println("集合中最後一個元素為: "+ts.last());    ///Object lower(Object e):返回集合中第一個小於e的元素,e不一定在集合中    ///Object higher(Object e):返回集合中第一個大於e的元素    ///如果沒有元素滿足的話,返回null    System.out.println("集合中第一個小於5的元素是: "+ts.lower(5));    System.out.println("集合中第一個大於5的元素是: "+ts.higher(5));    ///SortedSet subSet(Object e1,Object e2):返回Set從e1-e2之間的子集    System.out.println(ts.subSet(1,5));    ///SortSet headSet(Object e):返回集合中小於e的元素組成的子集    System.out.println(ts.headSet(6));    ///SortSet tailSet(Object e):返回集合中大於等於e元素組成的子集    System.out.println(ts.tailSet(1));}}

因為TreeSet是有序的,所以插入一個元素時總是要比較大小;這裡進行大小比較時總是調用對象obj1.compareTo(Object obj2)方法(返回正整數表示obj1大於obj2,返回負整數時表示obj1小於obj2,返回0時表示相等),只有兩個對象通過compareTo()比較返回0時,才認為兩個對象相等。這導致一個問題,不同的對象不能被同時插入到TreeSet中,因為不同的對象不能通過comparaTo()方法進行比較;當我們將不同的對象插入到TreeSet中時會引發異常。
如果我們想自己定義排序的規則,我們可以藉助Comparator介面。該介面中包含了一個int compare(T t1,T t2)的方法,該方法在t1>t2時返回正整數,在t1

package lkl;import java.util.TreeSet;import java.util.Comparator;public class TreeSetComparatorTest {///TreeSet原本是從從小到大輸出的,現在自己定製排序後///可以實現從大到小輸出    public static void main(String[] args){        TreeSet ts = new TreeSet(new Comparator(){           public int compare(Object o1,Object o2){                int m1= (int)o1;                int m2= (int)o2;                if(m1==m2)                    return 0;                if(m1>m2)                    return -1;                return 1;            }        });        ts.add(1);        ts.add(2);        ts.add(-1);        System.out.println(ts);    }}

最後要強調一句,如果我們向set中添加了可變的對象,然後又改變了該對象中的File,那麼可能造成該對象在set中”不可見”的情況;如果我們向set中加入了可變的對象,那麼我們不要在後面再改變其中File的值。

Java集合學習之Collection(2)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.