歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java裡的容器 Collection 簡介

容器也是Java面試經常問到的問題.  也是Java編程的其中1個難點,在一篇文章中很難全部講清楚, 我打算分幾篇逐步介紹。

一.  什麼是容器

1.1 容器的定義

Java裡的容器的定義很簡單:

容器(Collection)也稱為集合, 在java中就是指對象的集合.

這裡可以看出1個特性:  容器裡存放的都只能是對象. 實際上是存放對象的指針(頭部地址).

1.2 為何需要容器

在編程中我們通常需要將若干個對象進行集中處理.

當然. 通過數組也可以實現此需求.

但是數組也存在兩個硬傷:

1. 數組中元素的元素必須相同.

2. 數組的長度難以擴充

這裡解析一下:

假如A是1個類名, 那麼

A arr_A[] = new A[10];

標識在內存裡分配了1個數組, 數組的長度是10.

首先這個數組的元素只能是A的對象, 這個肯定的了.

假如想擴充這個數組, 那麼只能重新建立1個長度更長的數組, 並使用System.arraycopy() 函數把原數組的內容copy到新數組裡.

這樣的話十分耗費cpu資源和內存空間.

例子:

package Collection_kng;

class A{
    private int i;
    public A(int i){
        this.i = i;
    }

    public String toString(){
        return "" + this.i;
    }
}

public class Collect1{
    public static void f(){
        A[] arr_A = new A[10];
        int i;
        for(i = 0; i < 10; i++){
            arr_A[i] = new A(i);
        }   

        A[] arr_A2 = new A[11];
        System.arraycopy(arr_A,0,arr_A2,0,10);

        arr_A2[10] = new A(11);
        for(i = 0; i < 11; i++){
          System.out.println(arr_A2[i]);
        }   
    }
}

所以講: 對於1個數組, 一旦分配內存, 如果你想改變內存長度, 則效率會很低.

而使用容器的話, 可以解決這個兩個問題.

也就是講:  一個容器可以存放不同類型的對象(實際上是對象的指針),  而且可以靈活擴充容器的長度.

例子:

  public static void g(){
        ArrayList arr_l = new ArrayList();
        int i;
        for(i = 0; i < 10; i++){
            arr_l.add(new A(i));
        }   

        arr_l.add(new A(11));
        for(i = 0; i < 11; i++){
          System.out.println(arr_l.get(i));
        }   
    }

二.  容器的分類

在數學上, 我們可以把容器分為三種.

1.集(Set)

    Set相當於數學上的集合, Set中的所有元素是無序的, 而且不允許出現重復的元素.

2.列表(List)

    List相當於代數裡的隊列, 列表的元素是有序的, 而且允許包含重復成員.

    當然, 在java中List也可以分為數組列表(ArrayList)和鏈表(LinkedList), 它們兩者的使用方法類似, 但是內存存儲機制是不同的.

3.映射(Map)

    Map保存所謂的'鍵值對'(Key - Value)信息, 映射中不能出現重復的鍵(key), 每個鍵最多只能映射一個值.

在java中, sun公司為上面三個容器類型設計了三個對應的接口(interface), 這個三個接口分別是 Set List Map.

框架圖如下:

可以見到, 對於Set來講, Set接口繼承了Collection接口,  HashSet這個容器(類)實現了Set接口.

而ArrayList和 LinkedList都實現了List接口, List接口也是繼承自Collection接口.

而HashMap容器則是實現了Map接口, 而Map接口並不繼承與Collection接口哦.

由此看出, Java裡的容器類是基於接口(interface)構建的.

* Collection 定義了存取一組對象的方法, 其子接口Set和List分別定義了存儲方式.

* Map接口定義了存儲(key-value)映射對的方法.

很多時候, 大家還會見到另1中容器Vector, 其實Vector也是List容器一種, 但是Vector支持線程同步(裡面的方法都是sycronized的), 也就是允許多個線程同時操作1個Vector容器而不丟失數據.

而Arraylist並不是同步的.

三.  容器的若干個常用的方法

容器作為1個類, 當然有若干個常用的成員方法, 為了敘述方便, 先介紹這一點.

3.1 int size();

返回Collection中的元素個數.

3.2 boolean containsAll(collection c);

判斷1個容器是否包含另1個容器的所有元素, 這裡的元素指的的是對象的指針, 也就是對象的本身.

3.3 boolean add(Object e);

把1個對象添加到容器中, 這個方法是每種容器必有的方法.

3.4 boolean remove(Object e);

移除容器中首次出現的制定對象, 因為List容器根據次序不同允許存在重復的對象

3.5 get(int index);

獲得容器中第index個元素, 這個方法在List容器中十分常用, 但是不並適用於Set容器, 因為Set容器的元素是無序的.

3.6 Iterator iterator();

一些無序的容器很難通過循環來遍歷元素, 這時我們可以利用迭代器來遍歷容器元素.

3.7 Object[] toArray();

容器不是數組, 不能用下標來訪問容器的元素, 這個方法可以返回1個包含容器所有元素的數組.

3.8 重寫容器元素的toString()方法

很多時候, 我們需要循環輸出容器元素的對象.

例如:

for(...){
  System.out.println(arr1.get(i));
}

注意利用get()方法返回的是1個對象.

而println方法是輸出對象的toString()方法.  toString()方法在基類(Object)中被定義成輸出對象的類名+hashcode(). 

而很多時候我們需要的是輸出對象的其他有用信息(例如關鍵成員的值)

所以強烈建議:

  為所有有可能放入容器的類重寫toString()方法.

四.  Collections 類

上面提到了, Collection其實是1個接口, 但是Java裡也存在1個類叫Collections,  而這個Collections也是跟容器有關的.

我們常用的容器, 例如Arraylist, HashSet, Linkedlist等都是基於Collection接口實現的.

所以 Collections並不是上述容器的超類.

實際上, 在java裡的容器(例如Arraylist, Linklist)類只提供了一些簡單的操作方法, 如add(), get(), size()等.

而一些復雜的功能, 例如排序(sort), 倒置(reverst),則沒用提供.

所以Java提供了另1個類Collections, 集合了很多隊容器進行復雜操作的靜態方法. 這個就是Collections類的意義.

下面列舉若干Collections類的常用方法

4.1 void sort(List);

對List容器內的元素排序, 前提是容器內元素的類已經實現Comparable 接口(可以比較的)

下一篇文章會詳細提到.

4.2 void Shuffle(List);

對List容器的元素進行隨機排序.

4.3 void reverst(List);

就是傳說中的倒置, 隊List容器內的元素進行逆排序, 一般沒什麼用..

4.4 void Fill(List,Object);

把容器內的所有元素都替換為1個制定對象(object)

4.5 void Copy(List dest,List src);

把容器src裡的內容復制到dest容器

4.6 int bianrySearch(List,Object);

對於已排序的容器, 利用折半查找法找出制定對象.

Copyright © Linux教程網 All Rights Reserved