Collection表示一組稱爲其元素的對象,Collection
接口用於傳遞須要最大通用性的對象集合,例如,按照慣例,全部通用集合實現都有一個帶有Collection
參數的構造函數,此構造函數(稱爲轉換構造函數)初始化新集合以包含指定集合中的全部元素,不管給定集合的子接口或實現類型如何,換句話說,它容許你轉換集合的類型。html
例如,假設你有一個Collection<String> c
,它能夠是List
、Set
或其餘類型的Collection
,這個語法建立一個新的ArrayList
(List
接口的一個實現),初始化包含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
接口能夠知足你的指望,它有告訴你集合中有多少元素(size
、isEmpty
)的方法,檢查給定對象是否在集合中的方法(contains
),從集合中添加和刪除元素的方法(add
、remove
),和在集合上提供迭代器的方法(iterator
)。安全
add
方法的定義已經足夠普遍,所以對於容許重複的集合以及不重複的集合都有意義,它保證Collection
在調用完成後將包含指定的元素,而且若是Collection
因調用而更改,則返回true
。相似地,remove
方法旨在從Collection
中刪除指定元素的單個實例,假設它包含要開始的元素,而且若是結果修改了集合則返回true
。oracle
有三種遍歷集合的方法:(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的一部分,這些包括對整個集合進行操做的方法,例如containsAll
、addAll
、removeAll
等,不要將這些方法與JDK 8中引入的聚合操做混淆。新聚合操做與現有批量操做(containsAll
、addAll
等)之間的主要區別在於舊版本都是可變的,這意味着它們都修改了底層集合,相反,新的聚合操做不會修改底層集合。使用新的聚合操做和lambda表達式時,必須注意避免突變,以避免在之後從並行流運行代碼時引入問題。
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
構造,當你須要:
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
,則addAll
、removeAll
和retainAll
方法都返回true
。
做爲批量操做功能的一個簡單示例,請考慮如下語法,從Collection
c
中刪除指定元素e
的全部實例。
c.removeAll(Collections.singleton(e));
更具體地說,假設你要從Collection
中刪除全部null
元素。
c.removeAll(Collections.singleton(null));
這個語法使用Collections.singleton
,這是一個靜態工廠方法,它返回一個只包含指定元素的不可變Set
。
toArray
方法是做爲集合和舊API之間的橋樑提供的,這些API指望輸入上的數組,數組操做容許將Collection
的內容轉換爲數組,沒有參數的簡單形式建立一個新的Object
數組,更復雜的形式容許調用者提供數組或選擇輸出數組的運行時類型。
例如,假設c
是Collection
,如下代碼段將c
的內容轉儲到新分配的Object
數組中,該數組的長度與c
中的元素數相同。
Object[] a = c.toArray();
假設已知c
只包含字符串(可能由於c
的類型爲Collection<String>
),如下代碼段將c
的內容轉儲到新分配的String
數組中,該數組的長度與c
中的元素數相同。
String[] a = c.toArray(new String[0]);