Java集合類的學習(四)——Set

來源:互聯網
上載者:User
文章目錄
  • 1.5.1        概述
  • 1.5.2        常用方法
1.5        Set1.5.1        概述

Java 中的Set和正好和數學上直觀的集(set)的概念是相同的。Set最大的特性就是不允許在其中存放的元素是重複的。根據這個特點,我們就可以使用Set 這個介面來實現前面提到的關於商品種類的儲存需求。Set 可以被用來過濾在其他集合中存放的元素,從而得到一個沒有包含重複新的集合。

1.5.2        常用方法

按照定義,Set 介面繼承 Collection 介面,而且它不允許集合中存在重複項。所有原始方法都是現成的,沒有引入新方法。具體的 Set 實作類別依賴添加的對象的 equals() 方法來檢查等同性。

我們簡單的描述一下各個方法的作用:

u     public int size() :返回set中元素的數目,如果set包含的元素數大於Integer.MAX_VALUE,返回Integer.MAX_VALUE 

u     public boolean isEmpty() :如果set中不含元素,返回true 

u     public boolean contains(Object o) :如果set包含指定元素,返回true 

u     public Iterator iterator()

l         返回set中元素的迭代器 

l         元素返回沒有特定的順序,除非set是提高了該保證的某些類的執行個體 

u     public Object[] toArray() :返回包含set中所有元素的數組 

u     public Object[] toArray(Object[] a) :返回包含set中所有元素的數組,返回數組的運行時類型是指定數組的運行時類型 

u     public boolean add(Object o) :如果set中不存在指定元素,則向set加入

u     public boolean remove(Object o) :如果set中存在指定元素,則從set中刪除 

u     public boolean removeAll(Collection c) :如果set包含指定集合,則從set中刪除指定集合的所有元素 

u     public boolean containsAll(Collection c) :如果set包含指定集合的所有元素,返回true。如果指定集合也是一個set,只有是當前set的子集時,方法返回true 

u     public boolean addAll(Collection c) :如果set中中不存在指定集合的元素,則向set中加入所有元素 

u     public boolean retainAll(Collection c) :只保留set中所含的指定集合的元素(可選操作)。換言之,從set中刪除所有指定集合不包含的元素。 如果指定集合也是一個set,那麼該操作修改set的效果是使它的值為兩個set的交集 

u     public boolean removeAll(Collection c) :如果set包含指定集合,則從set中刪除指定集合的所有元素 

u     public void clear() :從set中刪除所有元素 

“集合架構” 支援 Set 介面兩種普通的實現:HashSet 和 TreeSet以及LinkedHashSet。下表中是Set的常用實作類別的描述:

 

 

簡述 

實現

操作特性 

成員要求 

Set 

成員不能重複 

HashSet

外部無序地遍曆成員。 

成員可為任意Object子類的對象,但如果覆蓋了equals方法,同時注意修改hashCode方法。 

TreeSet

外部有序地遍曆成員; 

附加實現了SortedSet, 支援子集等要求順序的操作 

成員要求實現Comparable介面,或者使用Comparator構造TreeSet。成員一般為同一類型。 

LinkedHashSet

外部按成員的插入順序遍曆成員 

成員與HashSet成員類似 

 

在更多情況下,您會使用 HashSet 儲存重複自由的集合。同時HashSet中也是採用了Hash演算法的方式進行存取對象元素的。所以添加到 HashSet 的對象對應的類也需要採用恰當方式來實現 hashCode() 方法。雖然大多數系統類別覆蓋了 Object 中預設的 hashCode() 實現,但建立您自己的要添加到 HashSet 的類時,別忘了覆蓋 hashCode()。

對於Set的使用,我們先以一個簡單的例子來說明: 

import java.util.*;

public class HashSetDemo {

public static void main(String[] args) {

Set set1 = new HashSet();

if (set1.add("a")) {//添加成功

System.out.println("1 add true");

}

if (set1.add("a")) {//添加失敗

System.out.println("2 add true");

}

set1.add("000");//添加對象到Set集合中

set1.add("111");

set1.add("222");

System.out.println("集合set1的大小:"+set1.size());

System.out.println("集合set1的內容:"+set1);

set1.remove("000");//從集合set1中移除掉 "000" 這個對象

System.out.println("集合set1移除 000 後的內容:"+set1);

System.out.println("集合set1中是否包含000 :"+set1.contains("000"));

System.out.println("集合set1中是否包含111 :"+set1.contains("111"));

Set set2=new HashSet();

set2.add("111");

set2.addAll(set1);//將set1 集合中的元素全部都加到set2中

System.out.println("集合set2的內容:"+set2);

set2.clear();//清空集合 set1 中的元素

System.out.println("集合set2是否為空白 :"+set2.isEmpty());

Iterator iterator = set1.iterator();//得到一個迭代器

while (iterator.hasNext()) {//遍曆

Object element = iterator.next();

System.out.println("iterator = " + element);

}

//將集合set1轉化為數組

Object s[]= set1.toArray();

for(int i=0;i<s.length;i++){

System.out.println(s[i]);

}

}

}

程式執行的結果為:

1 add true

集合set1的大小:4

集合set1的內容:[222, a, 000, 111]

集合set1移除 000 後的內容:[222, a, 111]

集合set1中是否包含000 :false

集合set1中是否包含111 :true

集合set2的內容:[222, a, 111]

集合set2是否為空白 :true

iterator = 222

iterator = a

iterator = 111

222

a

111

從上面的這個簡單的例子中,我們可以發現,Set中的方法與直接使用Collection中的方法一樣。唯一需要注意的就是Set中存放的元素不能重複。

我們再看一個例子,來瞭解一下其它的Set的實作類別的特性:

package c08;

import java.util.*;

public class SetSortExample {

  public static void main(String args[]) {

    Set set1 = new HashSet(); 

    Set set2 = new LinkedHashSet();

    for(int i=0;i<5;i++){

     //產生一個隨機數,並將其放入Set中

     int s=(int) (Math.random()*100);

      set1.add(new Integer( s));

      set2.add(new Integer( s));

      System.out.println("第 "+i+" 次隨機數產生為:"+s);

    }

    System.out.println("未排序前HashSet:"+set1);

    System.out.println("未排序前LinkedHashSet:"+set2);

    //使用TreeSet來對另外的Set進行重構和排序

    Set sortedSet = new TreeSet(set1);

    System.out.println("排序後 TreeSet :"+sortedSet);

  }

}

該程式的一次執行結果為:

第 0 次隨機數產生為:96

第 1 次隨機數產生為:64

第 2 次隨機數產生為:14

第 3 次隨機數產生為:95

第 4 次隨機數產生為:57

未排序前HashSet:[64, 96, 95, 57, 14]

未排序前LinkedHashSet:[96, 64, 14, 95, 57]

排序後 TreeSet :[14, 57, 64, 95, 96]

從這個例子中,我們可以知道HashSet的元素存放順序和我們添加進去時候的順序沒有任何關係,而LinkedHashSet 則保持元素的添加順序。TreeSet則是對我們的Set中的元素進行排序存放。

一般來說,當您要從集合中以有序的方式抽取元素時,TreeSet 實現就會有用處。為了能順利進行,添加到 TreeSet 的元素必須是可排序的。 而您同樣需要對添加到TreeSet中的類對象實現 Comparable 介面的支援。對於Comparable介面的實現,在前一小節的Map中已經簡單的介紹了一下。我們暫且假定一棵樹知道如何保持 java.lang 封裝程式器類元素的有序狀態。一般說來,先把元素添加到 HashSet,再把集合轉換為 TreeSet 來進行有序遍曆會更快。這點和HashMap的使用非常的類似。

其實Set的實現原理是基於Map上面的。通過下面我們對Set的進一步分析大家就能更加清楚的瞭解這點了。

1.5.3         實現原理

Java中Set的概念和數學中的集合(set)一致,都表示一個集內可以存放的元素是不能重複的。

前面我們會發現,Set中很多實作類別和Map中的一些實作類別的使用上非常的相似。而且前面再講解Map的時候,我們也提到:Map中的“索引值對”,其中的“鍵”是不能重複的。這個和Set中的元素不能重複一致。我們以HashSet為例來分析一下,會發現其實Set利用的就是Map中“鍵”不能重複的特性來實現的。

先看看HashSet中的有哪些屬性:

再結合建構函式來看看:

通過這些方法,我們可以發現,其實HashSet的實現,全部的操作都是基於HashMap來進行的。我們看看是如何通過HashMap來保證我們的HashSet的元素不重複性的:

看到這個操作我們可以發現HashSet的巧妙實現:就是建立一個“索引值對”,“鍵”就是我們要存入的對象,“值”則是一個常量。這樣可以確保,我們所需要的儲存的資訊之是“鍵”。而“鍵”在Map中是不能重複的,這就保證了我們存入Set中的所有的元素都不重複。而判斷是否添加元素成功,則是通過判斷我們向Map中存入的“索引值對”是否已經存在,如果存在的話,那麼傳回值肯定是常量:PRESENT ,表示添加失敗。如果不存在,傳回值就為null 表示添加成功。

我們再看看其他的方法實現:

瞭解了這些後,我們就不難理解,為什麼HashMap中需要注意的地方,在HashSet中也同樣的需要注意。其他的Set的實作類別也是差不多的原理。

至此對於Set我們就應該能夠比較好的理解了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.