Java中容器的使用


 

由上面的圖可以非常清楚的看到,Java中的容器的繼承結構

在頂層有很多接口,這些接口聲明了很多的基本的抽象方法,之后的許多類按照不同的方式實現這些接口,

同時可能在增加一些自己的方法,從而形成了不同功能的容器,比如:ArrayList類與LinkedList類都繼承了List接口,

但是他們在實現List的接口時,方法體並不一樣,這樣一來就形成了不一樣的容器,這些容器都位於java.util包中

 

接下來我們將一一介紹這些容器的功能,當然我們不可能將容器的所有的知識全部不漏的講解,我們只是將一些

思想講解一下,使我們對容器有一個整體的認識,至於一些具體的方法如何使用,需要在用時查詢官方文檔

首先我們先對List、Set、Queue、Map接口的功能做一個介紹:

①List類型的容器實際上就相當於一個長度可變的

“對象數組”,和向量的概念是相同的

②Set類型的容器實際上相當於一個“對象集合”

  這樣的容器中是不允許加入重復的元素的,並且

  對於其中的元素並沒有一種排序的概念,和集合

  是一個概念

③Queue類型的容器實際上相當於一個“對象隊列”

④Map類型的容器中的每個元素包含一對兒鍵對象和

   值對象,即在關鍵字對象和值對象之間產生一種映射關系,通過鍵對象類查找值對象

  接下來,我們介紹逐一介紹這些具體的容器都有什么功能

 

  實例:

     Collection<String> c = new ArrayList<String>

(Array.asList("A","B","C"));

一、Collection 接口

這個接口只一個抽象度非常高的接口,這其中聲明了那些實現了他的容器類都具有的特性方法,也就是諸如:

ArrayList類、LinkedList類、HashSet類等其中的繼承自Collection接口的方法的實現方式都是一樣的,

比如:boolean add(E e) 這個方法在所有的這些類中都是將一個元素加入容器當中;

即Collection中的抽象方法都是從“一堆元素”的概念上抽象出來的Collection接口的常用抽象方法有:

① public Boolean add(E e) 

   向容器當中添加一個元素

②boolean addAll(Collection<? extends E> c)

   向當前的容器中加入指定的Collection類型的容器的所有元素

③void clear()

   移除容器當中的所有的元素

④boolean contains(Object obj)

  判定當前的容器中是否有指定的元素,我們想肯定調用了equals()方法了

⑤boolean containsAll(Collection<?> c)

  判定當前容器中是否包含了,指定的容器中的所有的元素

⑥boolean isEmpty()

     判定當前的容器是否為空

   ⑦Iterator<E> iterator()

     返回當前容器對應的迭代器

   ⑧boolean remove(Object obj)

     如果容器當中含有該元素,則將之刪除

   ⑨boolean retainAll(Collection<?> C)

     將當前的容器中的元素和指定的容器元素取交集存入當前容器中

   10.int size ()

      返回容器的元素數目

   11.Object[] toArray()

      根據當前容器中的元素創建一個對象數組

二、實用類Collections

在上面的圖中的右下角有兩個實用類:Collections類

和Arrays類,Arrays類中的靜態方法主要是操作數組的,而Collection類中也有很多靜態的方法是用來操作List、Set、Queue、Map類型的容器的,

這兩個實用類都位於java.util包中

在Arrays類中也有一個操縱容器的方法

static    List<T>

asList(T... a)

返回有可變參數列表創建的List類型的容器對象,並返回容器的引用,如:

String [] strArray = {“123”,”wr”,”fsdf”};

List <String> ls = Array.asList(strArray);

在Collection類中的靜態方法,能夠實現容器中元素的替換、刪除、排序、整個復制等等,具體的就不在多講

三、List(列表)

  像數組一樣,List也能建立數字索引與對象的關聯,表達的是數據結構中的線性表的概念,List接口的常用實現類是:ArrayList和LinkedList

 

  ①ArrayList類

    就像名子顯示的那樣,ArrayList是線性表中的數組,也就是說這個類中的數據域實際上就是一個對象數組,

因此,他有數組的一切的特性,還有同時封裝在一起的方法

因此對於查找來說,速度是非常的快的,但是刪除與插入操作就相對較慢,而且ArrayList是線程不安全的

 

  ②LinkedList類

     就像名字顯示的那樣,LinkedList是線性表當中的鏈表,也就是說這個類中的數據域實際上就是一個對象鏈表,

還有同時封裝在一起的方法,值的注意的是內部的這個鏈表是一個雙向的循環鏈表,

也就是說,插入語刪除操作是非常快的,但是查找較慢

     另外需要非常注意的是,LinkedList類還繼承了Queue接口,

LinkedList類中單獨還有addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()等方法,

這就是的LinkedList類的對象能夠用作隊列和棧來使用,同樣,LinkedList是線程不安全的

四、Set(集合)

1、Set 中不接受任何重復的元素,如果試圖將重復的對象加到同一個Set對象當中的話,是不能加入的;所謂的相同的對象,

是根據equals(參數)方法來判定的,這就要涉及到該方法的重寫問題了,這在之前已經討論過了

 

2、一般Set最常用於判定一個指定元素的歸屬性問題,即判定一個元素是否已經在在當前的集合當中了!可見查找

是Set型容器的最常用的、最重要的方法了;Set與Collection具有完全一樣的接口,實際上Set就是Collection,只是應用的行為不同罷了!

3、雖然Set有HashSet、TreeSet、LinkedSet三種實現類,但是在《thinking in java》 中明確指出,

對於查找而言HashSet類失效率最高的一個類,所以在沒有特殊的要求時,使用HashSet是最好的選擇

 

<HashSet類>

1、這個類的內部有一個HasMap實例對象作為其成員域,

這說明在HashSet類的實例對象中的元素都是按照哈希表的形式存儲在HashMap對象中了,這也就說明了,HashSet類的查找效率是非常高的

2、通過add(參數)向HashSet對象當中,添加元素時,首先會調用hasCode()方法,計算出該元素的存放位置,

比較該位置的元素是否與要添加的元素相同,所以又要調用equals()方法;同時在查找時也要調用hashCode方法;

這就要求我們將equals()方法和hashCode方法同時重寫,保證兩個方法相匹配,即保證:

當兩個元素對象“相等時”,那么兩個元素對象應該生成相同的散列碼

這就用到了另一份文檔“Java中的hashCode()方法的深入剖析.doc”(其中那個例子非常有代表性)

我們在獲得這個容器中的每個元素時,可以使用簡化的for語句實現,這是允許的,可以查閱一下簡化的for語句的使用前提

 

五、Queue(隊列)

也就是說,Queue類型的容器專門用來用作容器來使用的

具有隊列的特性

①利用LinkedList類型的容器實現普通的隊列、雙向隊列、棧等數據結構(LinkedList類同時實現了Queue接口),

我們可以通過將LinkedList的對象向上轉型到Queue,這樣一來的話就只能使用繼承自Queue接口的專門用於隊列的方法,

使LinkedList對象看起來像一個完完全全的隊列容器;對於雙向隊列,java中有一個專門用於實現雙端隊列的接口Deque,位於java.uitl包中,

而且LinkedList類也實現了該接口,所以同樣可以將LinkedList對象向上轉型形成一個單純的雙端隊列

②PriorityQueue(優先級隊列)

所謂的優先級隊列就是在該隊列的內部有一個堆的數據結構,實現了每次出對的元素,都是優先級最高的元素;

但是程序是如何知道每個元素的優先級的呢,這里有兩種方式:自然方式和人為指定方式

所謂的自然方式是指,如果容器中的元素對象是String、Integer、或者是Character類型的內嵌數據類型的話,

那么這種優先級是程序已經自行規定好的了,即“較小”的擁有較高的優先級;但是對於實際問題中的很多的元素都不是內嵌的數據類型,

那么就要人為的指定優先級的設定規則,解決這一問題的方法就是,使元素類實現Comparable

接口,這個接口中只有一個方法

public int compareTo(Object obj)

只要在元素類中將該方法實現的話,那么程序就會自行的根據這個方法來設定優先級,如:

 

注意:對於PriorityQueue來說,他的遍歷器不能保證按照優先級次序便利所有的元素

 

六、Map(映射)

Map(映射)是一種將鍵對象和值對象進行映射的集合,需要注意的是如果值對象是Map類型的話那么,就形成了多級映射;

在實現該接口的類中效率最高的一個就是HashMap類,一般在沒有特殊的要求的情況下最好及使用這個類型的容器,

這個容器的用法和前面講過的Hashtable容器非常相近,可以參照該部分的內容進行理解,

其中最終要的一點是對於hashCode()和euqals()方法的重寫;

另外需要注意的一點是:如果在哈希表的應用中,迭代性能比查找性能更加站上風,那么在設定初始容量時,

就應該盡量的不讓初始容量太高,而同時讓裝填因子設定的得盡量的高;如果是說實際使用哈希表的時候,

有非常多的鍵值對要加入到該容器中的話,使用足夠大的初始容量創建該容器,將使得映射關系更加有效的存貯,

因為如果初始容量設定的過於小的話,那么容器就會按照規則不斷的進行擴充,那么就會耗費非常多的時間

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM