Java™ 教程(Collection接口)

Collection接口

Collection表示一組稱爲其元素的對象,Collection接口用於傳遞須要最大通用性的對象集合,例如,按照慣例,全部通用集合實現都有一個帶有Collection參數的構造函數,此構造函數(稱爲轉換構造函數)初始化新集合以包含指定集合中的全部元素,不管給定集合的子接口或實現類型如何,換句話說,它容許你轉換集合的類型。html

例如,假設你有一個Collection<String> c,它能夠是ListSet或其餘類型的Collection,這個語法建立一個新的ArrayListList接口的一個實現),初始化包含c中的全部元素。java

List<String> list = new ArrayList<String>(c);

或者 — 若是你使用的是JDK 7或更高版本 — 你能夠使用菱形運算符:算法

List<String> list = new ArrayList<>(c);

Collection接口包含執行基本操做的方法,例如int size()boolean isEmpty()boolean contains(Object element)boolean add(E element)boolean remove(Object element)Iterator<E> iterator()編程

它還包含對整個集合進行操做的方法,例如boolean containsAll(Collection<?> c)boolean addAll(Collection<? extends E> c)boolean removeAll(Collection<?> c)boolean retainAll(Collection<?> c)void clear()segmentfault

還存在用於數組操做的額外方法(諸如Object[] toArray()<T> T[] toArray(T[] a))。api

在JDK 8及更高版本中,Collection接口還公開方法Stream<E> stream()Stream<E> parallelStream(),以從底層集合中獲取順序或並行流(有關使用流的更多信息,請參閱聚合操做的課程)。數組

若是Collection表示一組對象,Collection接口能夠知足你的指望,它有告訴你集合中有多少元素(sizeisEmpty)的方法,檢查給定對象是否在集合中的方法(contains),從集合中添加和刪除元素的方法(addremove),和在集合上提供迭代器的方法(iterator)。安全

add方法的定義已經足夠普遍,所以對於容許重複的集合以及不重複的集合都有意義,它保證Collection在調用完成後將包含指定的元素,而且若是Collection因調用而更改,則返回true。相似地,remove方法旨在從Collection中刪除指定元素的單個實例,假設它包含要開始的元素,而且若是結果修改了集合則返回trueoracle

遍歷集合

有三種遍歷集合的方法:(1)使用聚合操做(2)for-each構造(3)經過使用Iterators框架

聚合操做

在JDK 8及更高版本中,迭代集合的首選方法是獲取流並對其執行聚合操做,聚合操做一般與lambda表達式結合使用,以使編程更具表現力,使用更少的代碼行,如下代碼按順序遍歷一組形狀並打印出紅色對象:

myShapesCollection.stream()
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));

一樣,你能夠輕鬆地請求並行流,若是集合足夠大而且你的計算機具備足夠的核心,這多是有意義的:

myShapesCollection.parallelStream()
.filter(e -> e.getColor() == Color.RED)
.forEach(e -> System.out.println(e.getName()));

使用此API收集數據的方法有不少種,例如,你可能但願將Collection的元素轉換爲String對象,而後將它們鏈接起來,用逗號分隔:

String joined = elements.stream()
    .map(Object::toString)
    .collect(Collectors.joining(", "));

或者能夠把全部員工的工資加起來:

int total = employees.stream()
.collect(Collectors.summingInt(Employee::getSalary)));

這些只是你能夠使用流和聚合操做執行的一些示例,有關更多信息和示例,請參閱聚合操做的課程。

集合框架一直提供許多所謂的「批量操做」做爲其API的一部分,這些包括對整個集合進行操做的方法,例如containsAlladdAllremoveAll等,不要將這些方法與JDK 8中引入的聚合操做混淆。新聚合操做與現有批量操做(containsAlladdAll等)之間的主要區別在於舊版本都是可變的,這意味着它們都修改了底層集合,相反,新的聚合操做不會修改底層集合。使用新的聚合操做和lambda表達式時,必須注意避免突變,以避免在之後從並行流運行代碼時引入問題。

for-each構造

for-each構造容許你使用for循環簡明地遍歷集合或數組 — 請參閱for語句,如下代碼使用for-each構造在單獨的行上打印出集合的每一個元素。

for (Object o : collection)
    System.out.println(o);

迭代器

Iterator是一個使你能夠遍歷集合並須要時有選擇地從集合中刪除元素的對象,經過調用iterator方法得到集合的Iterator,如下是Iterator接口。

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); //optional
}

若是迭代具備更多元素,則hasNext方法返回true,而且next方法返回迭代中的下一個元素,remove方法從底層Collection中刪除next返回的最後一個元素,對next的每次調用只能調用remove方法一次,若是違反此規則則拋出異常。

請注意,Iterator.remove是在迭代期間修改集合的惟一安全方法,若是在迭代進行過程當中以任何其餘方式修改底層集合,則不指定此行爲。

使用Iterator而不是for-each構造,當你須要:

  • 刪除當前元素,for-each構造隱藏了迭代器,所以你沒法調用remove,所以,for-each構造不可用於過濾。
  • 並行迭代多個集合。

如下方法說明如何使用Iterator過濾任意Collection — 即遍歷集合刪除特定元素。

static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}

這段簡單的代碼是多態的,這意味着不管實現如何,它都適用於任何Collection,此示例演示了使用Java集合框架編寫多態算法是多麼容易。

集合接口批量操做

批量操做對整個Collection執行操做,你能夠使用基本操做實現這些簡寫操做,但在大多數狀況下,此類實現效率較低,如下是批量操做:

  • containsAll — 若是目標Collection包含指定Collection中的全部元素,則返回true
  • addAll — 將指定Collection中的全部元素添加到目標Collection
  • removeAll — 從目標Collection中刪除它們也包含在指定Collection中的全部元素。
  • retainAll — 從目標Collection中刪除全部未包含在指定Collection中的元素,也就是說,它僅保留目標Collection中也包含在指定Collection中的那些元素。
  • clear — 從集合中刪除全部元素。

若是在執行操做的過程當中修改了目標Collection,則addAllremoveAllretainAll方法都返回true

做爲批量操做功能的一個簡單示例,請考慮如下語法,從Collection c中刪除指定元素e的全部實例。

c.removeAll(Collections.singleton(e));

更具體地說,假設你要從Collection中刪除全部null元素。

c.removeAll(Collections.singleton(null));

這個語法使用Collections.singleton,這是一個靜態工廠方法,它返回一個只包含指定元素的不可變Set

集合接口數組操做

toArray方法是做爲集合和舊API之間的橋樑提供的,這些API指望輸入上的數組,數組操做容許將Collection的內容轉換爲數組,沒有參數的簡單形式建立一個新的Object數組,更復雜的形式容許調用者提供數組或選擇輸出數組的運行時類型。

例如,假設cCollection,如下代碼段將c的內容轉儲到新分配的Object數組中,該數組的長度與c中的元素數相同。

Object[] a = c.toArray();

假設已知c只包含字符串(可能由於c的類型爲Collection<String>),如下代碼段將c的內容轉儲到新分配的String數組中,該數組的長度與c中的元素數相同。

String[] a = c.toArray(new String[0]);

上一篇:集合接口

下一篇:Set接口

相關文章
相關標籤/搜索