概述
通過前文的學習,我們對容器的分類及常用容器類的作用有了基本的認識。本文將針對Collection容器的功能與使用進行細致分析。
基本操作
Collection集合抽象出的目的是為存放獨立元素的序列。
Collection接口定義的基本操作包含添加,移除,查找,遍歷等。具體API定義如下:
abstract boolean add(E e)
abstract boolean addAll(Collection<? extends E> c)
abstract boolean clear()
abstract boolean contains(Object o)
abstract boolean containsAll(Collection<? extends E> c)
abstract boolean equals(Object o)
abstract int hashCode()
abstract boolean isEmpty()
abstract Iterator<E> iterator()
abstract boolean remove(Object o)
abstract boolean removeAll(Collection<?> c)
abstract boolean retainAll(Collection<?> c)
abstract int size()
abstract Object[] toArray()
abstract <T> T[] toArray(T[] a)
這些操作可以按照具體作用來划分,下面我們結合一些實例來理解。
添加元素
package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
public class Adding {
public static void main(String[] args) {
//構造方法直接添加
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4));
//使用add方法
collection.add(5);
System.out.println(collection);
Integer[] Ints = {10, 11, 12};
//使用addAll方法
collection.addAll(Arrays.asList(Ints));
System.out.println(collection);
//Collections提供的addAll方法
Collections.addAll(collection, Ints);
System.out.println(collection);
}
}
輸出結果
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 10, 11, 12]
[1, 2, 3, 4, 5, 10, 11, 12, 10, 11, 12]
本例中,Arrays的asList方法可將數組轉換為List類型,我們可以通過構造方法直接初始化Collection實例。若想添加單個元素,直接調用add方法;想要添加一組元素,也可調用addAll方法。另一種比較高效方式是調用Collections的addAll方法。
辨析 Collection Collections
Collection與Collections同屬於集合類,但卻完全不同。這是Java開發者非常容易混淆的內容。
Collection是集合的頂層接口,而Collections則是一個工具類。Collections提供了許多靜態方法,從而能夠操作集合,對集合中的元素進行排序,添加以及搜索等操作。例如:
排序
package collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestCollections1{
public static void main(String[] args){
Integer[] a = {10, 30, 20, 9, 4, 1, 50};
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, a);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
輸出結果
[10, 30, 20, 9, 4, 1, 50]
[1, 4, 9, 10, 20, 30, 50]
Collections中實用的方法還有很多,下面列出一些常用方法的API,本文就不再一一贅述。
public static <T> boolean addAll(Collection<? super T> c, T... elements)
//二分搜索搜索列表指定元素
public static <T> int binarySearch(List<? extends T>, T key)
//將元素從一個列表復制到到另一個列表
public static <T> void copy(List<? super T> dest, List<? extends T> src);
//反轉列表
public static void reverse(List<?> list)
//隨機化列表
public static void shuffle(List<T> list)
//返回線程安全的collection
public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
刪除元素
package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class Removing{
public static void main(String[] args) {
String[] arr = {"I'm sorry","I'm coding", "I'm writing", "I'm learning", "I'm thinking"};
Collection<String> collection = new ArrayList<String>(Arrays.asList(arr));
Collection<String> c = new ArrayList<String>(Arrays.asList("I'm learning", "I'm thinking"));
System.out.println(collection);
//移除元素
collection.remove("I'm writing");
System.out.println(collection);
//移除一組元素
collection.removeAll(c);
System.out.println(collection);
//移除所有元素
collection.clear();
System.out.println(collection);
}
}
輸出結果
[I'm sorry, I'm coding, I'm writing, I'm learning, I'm thinking]
[I'm sorry, I'm coding, I'm learning, I'm thinking]
[I'm sorry, I'm coding]
[]
本例中,調用remove方法刪除集合中單個元素,通過removeAll方法刪除一組包含於collection中的元素,使用clear方法可移除集合所有元素。
訪問元素
觀察Collection定義的API可看出,Collection接口似乎沒有對訪問指定位置元素,遍歷列表提供合適的方法。contains、equals兩種方法可查找元素,卻也無法實現迭代,遍歷元素的目的。
這時就需要Iterator(迭代器)來為我們幫忙了,Collection中iterator()方法直接返回容器的Iterator,以遍歷整個容器。
迭代器
迭代器(Iterator)這一概念源自C++的STL(標准模板庫),使用者可直接遍歷容器而無需關心其結構類型,直接使用Iterator即可。Java中,Iterator的限制是只能單向遍歷容器。
用法
Iteraotr提供了以下三種方法
boolean hasNext()
E next()
void remove()
hasNext方法用於確定容器中是否還有元素,next方法獲得容器中下一個元素,remove方法刪除Iterator目前指向的元素。
舉個栗子
package collection;
import java.util.*;
public class EasyIteration{
public static void main(String[] args){
Integer[] Ints = {1, 2, 3, 8, 5};
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(Ints));
Iterator<Integer> it = collection.iterator();
//遍歷開始,hasNext控制邊界
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
it = collection.iterator();
for(int i = 0; i < 2; i++){
it.next();
//刪除元素
it.remove();
}
System.out.println(collection);
}
}
輸出結果
1 2 3 8 5
[3, 8, 5]
本例中,有了Iterator,我們就可以對容器中的元素進行訪問和刪除操作,而無需關心容器的具體類型。
UnspportedOperationException異常
UnspportedOperationException拋出的原因是使用了不當的容器操作。通常是由於嘗試修改固定長度的容器的緣故,調用Array.asList() 方法會返回這種容器。因為數組顯然是固定長度的容器,使用asList方法轉換為list也會保持這種屬性。
舉個栗子
package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
public class UnspportedTest{
public static void test(String msg, Collection<Integer> collection){
Integer[] arr = {1, 3, 4};
Collection<Integer> tc = Arrays.asList(arr);
//使用會修改容器的操作
System.out.println("****" + msg + "****");
try{
collection.add(5);
}catch(Exception e){
e.printStackTrace();
}
try{
Collections.addAll(collection, arr);
}
catch(Exception e){
e.printStackTrace();
}
try{
collection.retainAll(tc);
}
catch(Exception e){
e.printStackTrace();
}
try{
collection.remove(1);
}catch(Exception e){
e.printStackTrace();
}
try{
collection.removeAll(Arrays.asList(arr));
} catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
Integer[] arr = {1, 3, 1, 4, 1, 2};
Collection<Integer> c = Arrays.asList(arr);
Collection<Integer> c1 = new ArrayList<Integer>(c);
test("可修改", c1);
test("不可修改", c);
test("不可修改", Collections.unmodifiableCollection(c1));
}
}
輸出結果
****可修改****
****不可修改****
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at collection.UnspportedTest.test(UnspportedTest.java:13)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at java.util.Collections.addAll(Collections.java:3845)
at collection.UnspportedTest.test(UnspportedTest.java:18)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractCollection.remove(AbstractCollection.java:291)
at collection.UnspportedTest.test(UnspportedTest.java:30)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractCollection.removeAll(AbstractCollection.java:373)
at collection.UnspportedTest.test(UnspportedTest.java:35)
at collection.UnspportedTest.main(UnspportedTest.java:47)
****不可修改****
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
at collection.UnspportedTest.test(UnspportedTest.java:13)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
at java.util.Collections.addAll(Collections.java:3845)
at collection.UnspportedTest.test(UnspportedTest.java:18)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.remove(Collections.java:1078)
at collection.UnspportedTest.test(UnspportedTest.java:30)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.removeAll(Collections.java:1088)
at collection.UnspportedTest.test(UnspportedTest.java:35)
at collection.UnspportedTest.main(UnspportedTest.java:48)
本例中,test方法包含了會修改數組長度的方法。為其傳入固定長度的容器引用,會拋出UnspportedOperationException異常。
從輸出結果可知,若在為容器分配空間時將asList方法得到的list通過構造方法初始化,會得到一個尺寸可調的Collection實例,允許調用所有方法。 若直接將asList生成的list返回給容器實例,就會附加不可修改尺寸的屬性,拋出異常。 最后我們證明了調用Collections工具類的unmodifiableCollection方法可人為的給普通容器加上不可修改的特性,同樣會拋出UnspportedOperationException異常。
總結
Collection接口是容器類最上層的接口之一,一般通過向上轉型的方式來實現該接口。本文針對Collection定義的基本操作,功能與用途,與Collections的關系,以及因不當操作而可能拋出的UnspportedOperationException異常進行了深入的分析。
后續,將繼續和大家討論繼承Collection接口的List,Set,Queue 以及 Map的基本操作與機制。
作者: I'm coding
鏈接:ACFLOOD
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
如果您覺得本文對您有所幫助,就給俺點個贊吧!