先來看幾道題目:
1、
public static void main(String[] args) {Set<String> set = new HashSet<String>();set.add("Java");set.add("JEE");set.add("Spring");set.add("Hibernate");set = Collections.unmodifiableSet(set);set.add("Ajax"); // not allowed.}
可以看到,建立不可變集合主要是調用了Collections的unmodifiableSet()方法,而
public static void main(String args[]) { List<String> list=new ArrayList(); list.add("A"); list.add("B"); list.add("C"); list.add("A"); // List中允許元素重複 for(int i=0;i<list.size();i++) System.out.print(" "+list.get(i));// A B C A // 去除重複的元素且保持原有元素的順序 List list2=new testD().function(list); for(int i=0;i<list2.size();i++) System.out.print(" "+list2.get(i));// A B C }public <e> List<e> function (List<e> list) { return new ArrayList<e>(new LinkedHashSet<e>(list));}
其實如上的兩道題目並不難,只是沒有對集合瞭解的更深。下面就來大概的看一下集合吧。集合的繼承類如下所示。
大概能夠分為三種不同的集合,List、Set和Map,還有一些輔助的工具類,像Collections、Arrays等,各個集合的比較情況如。
// Implementing this interface allows an object to be the target of the "foreach" statement.public interface Iterable<T> { Iterator<T> iterator();}
介面中定義了一個迭代器,可以使用增強for迴圈(foreach)對集合進行遍曆。Iterator類的原始碼如下:
/** * Iterator takes the place of Enumeration. Iterators differ from enumerations in two ways: * * <li> Iterators allow the caller to remove elements from the * underlying collection during the iteration with well-defined * semantics. * <li> Method names have been improved. */public interface Iterator<E> { boolean hasNext(); E next(); /** * Removes from the underlying collection the last element returned * by this iterator (optional operation). */ void remove();}
繼續看Collection介面,原始碼如下:
public interface Collection<E> extends Iterable<E> { // 尋找操作 int size(); boolean isEmpty(); boolean contains(Object o); boolean containsAll(Collection<?> c); // 增加操作 boolean add(E e); boolean addAll(Collection<? extends E> c); // 刪除操作 boolean remove(Object o); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); // 集合轉換 Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); // 提供equals()和hashCode() boolean equals(Object o); int hashCode();}
這個介面是專門針對集合定義了各種操作,他定義了常用集合的一般操作,但是由於抽象層次較高,所以一般一個具體的集合實作類別,如ArrayList、HashMap等都不會直接繼承這個介面,而是繼承這個介面的一些子類來實現。所以說每個集合的具體實作類別都直接或間接繼承了這個介面。
4、List所依賴的介面及抽象類別:
尋找集合架構圖後可知,具體的List實作類別繼承了AbstractCollection抽象類別並且實現了List介面。List介面中又定義了哪些操作呢?
public interface List<E> extends Collection<E> { // Query Operations int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); // Modification Operations boolean add(E e); boolean remove(Object o); // Bulk Modification Operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean addAll(int index, Collection<? extends E> c); boolean removeAll(Collection<?> c); boolean retainAll(Collection<?> c); void clear(); // Comparison and hashing boolean equals(Object o); int hashCode(); // Positional Access Operations // Returns the element at the specified position in this list. E get(int index); E set(int index, E element);// 修改指定位置的元素 void add(int index, E element); E remove(int index); // Search Operations int indexOf(Object o); int lastIndexOf(Object o); // List Iterators ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); // View List<E> subList(int fromIndex, int toIndex);}
如上的一些方法都在Collection中定義過的,這裡完全可以省略,只是為了明了,同時這個介面中還定義了一些更為具體的方法,這些方法是針對List類型的集合而設定的。這樣,Map集合就可以只繼承Collection,而不用實現List集合中的方法。所以說,如果在實際應用中,只針對List集合,則完全可以使用List介面,因為這個細化的介面中可以看到許多針對List而定義的方法。如果不確定集合類型,或者是需要List集合與Map集合互操作,那就需要使用Collection介面了。
對於List遍曆操作又定義出了更加細化的一個迭代介面,這個介面繼承了Iterator介面,如下:
public interface ListIterator<E> extends Iterator<E> { // Query Operations boolean hasNext(); E next(); boolean hasPrevious(); E previous(); int nextIndex(); int previousIndex(); void remove(); void set(E e); void add(E e);}
這個介面中增加了不少針對List集合的遍曆尋找方法。在List介面中使用ListIterator,類似與AbstractCollection使用Iterator一樣。
/** * This class provides a skeletal implementation of the <tt>Collection</tt> * interface, to minimize the effort required to implement this interface. <p> */public abstract class AbstractCollection<E> implements Collection<E> { // protected類型的,以便子類能夠順利調用 protected AbstractCollection() { } public abstract Iterator<E> iterator();// 定義一個iterator的抽象方法 public abstract int size(); public boolean isEmpty() { return size() == 0; } public boolean contains(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) if (it.next()==null) return true; } else { while (it.hasNext()) if (o.equals(it.next())) return true; } return false; } public boolean remove(Object o) { Iterator<E> it = iterator(); if (o==null) { while (it.hasNext()) { if (it.next()==null) { it.remove(); return true; } } } else { while (it.hasNext()) { if (o.equals(it.next())) { it.remove(); return true; } } } return false; } public Object[] toArray() { // Estimate size of array; be prepared to see more or fewer elements Object[] r = new Object[size()]; Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) // fewer elements than expected return Arrays.copyOf(r, i); r[i] = it.next(); } return it.hasNext() ? finishToArray(r, it) : r; } public <T> T[] toArray(T[] a) { // Estimate size of array; be prepared to see more or fewer elements int size = size(); T[] r = a.length >= size ? a : (T[])java.lang.reflect.Array .newInstance(a.getClass().getComponentType(), size); Iterator<E> it = iterator(); for (int i = 0; i < r.length; i++) { if (! it.hasNext()) { // fewer elements than expected if (a != r) return Arrays.copyOf(r, i); r[i] = null; // null-terminate return r; } r[i] = (T)it.next(); } return it.hasNext() ? finishToArray(r, it) : r; } // 定義分配數組最大的棧尺寸,防止溢出 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * Reallocates the array being used within toArray when the iterator * returned more elements than expected, and finishes filling it from * the iterator. */ private static <T> T[] finishToArray(T[] r, Iterator<?> it) { int i = r.length; while (it.hasNext()) { int cap = r.length; if (i == cap) { int newCap = cap + (cap >> 1) + 1; // overflow-conscious code if (newCap - MAX_ARRAY_SIZE > 0) newCap = hugeCapacity(cap + 1); r = Arrays.copyOf(r, newCap); } r[i++] = (T)it.next(); } // trim if overallocated return (i == r.length) ? r : Arrays.copyOf(r, i); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError ("Required array size too large"); return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE : MAX_ARRAY_SIZE; } // Modification Operations // 省略 ... // String conversion /** * Returns a string representation of this collection. The string * representation consists of a list of the collection's elements in the * order they are returned by its iterator, enclosed in square brackets * ("[]"). Adjacent elements are separated by the characters * ", " (comma and space). */ public String toString() { Iterator<E> it = iterator(); if (! it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { E e = it.next(); sb.append(e == this ? "(this Collection)" : e); if (! it.hasNext()) return sb.append(']').toString(); sb.append(',').append(' '); } }}
從如上的兩個方法contains()和remove()方法可以看出,其具體的子類如果繼承了這兩個方法,那麼集合中就可以添加
ArrayList aList=new ArrayList();aList.add("a");aList.add("b");aList.add("d");aList.add(null);// ArrayList中允許有null值System.out.println(aList.size());//4Iterator it=aList.listIterator();while(it.hasNext()){System.out.println(it.next());// a b d null}
可以看到,在ArrayList集合中完全將
5、Set所依賴的介面及抽象類別:
Set介面繼承了Collection,其中也定義了一些針對Set集合定義的一些方法,可以看到,與List介面中定義的方法一樣。
public interface Set<E> extends Collection<E> { // Query Operations int size(); boolean isEmpty(); boolean contains(Object o); Iterator<E> iterator(); Object[] toArray(); <T> T[] toArray(T[] a); // Modification Operations boolean add(E e); boolean remove(Object o); // Bulk Operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean retainAll(Collection<?> c); boolean removeAll(Collection<?> c); void clear(); // Comparison and hashing boolean equals(Object o); int hashCode();}
如上介面中定義的方法都一樣,只是實現不一樣。但是這樣分開為List和Set等集合定義介面的好處就是,如果針對某一個具體集合的操作有一個特殊的操作,那麼只在這個介面中定義即可,其他集合不會受到任何影響。
6、Map所依賴的介面及抽象類別: