今天開始,要說Java內,非常重要的一個東西,就是集合,java著名的集合框架。
Part1:將Java集合框架的接口和類庫分開!
我們來舉一個關於隊列接口,Queue的例子:
隊列接口的最簡單形式可能是這樣:
public interface Queue<E>
{
void add(E element);
E remove();
int size();
}
那我們就可以通過Implements來實現它:
public class CircularArrayQueue<E> implements Queue<E>
{
private int head;//如果是LinkListQueue這裏int換成Link
private int tail;
CircularArrayQueue(int capacity){...};
public void add(E element);
public E remove();
public int size();
private E[] elements;
}
只有在構建集合對象時,使用具體的類纔有意義。這時候,我們可以是使用接口類型存放集合的引用。
Queue<Customer> expressLane = new CircularArrayQueue<>(100);
expressLane.add(new Customer("Harry"));
利用這種方式,我們可以有一些方便,比如說存在兩個實現Queue的類,一個是LinkedListQueue,另一個是CircularArrayQueue。我們拿上面的例子來說,如果我們覺的LinkedListQueue是個更好的選擇,那我們只需要將代碼修改爲:
Queue<Customer>expressLane = new LinkedListQueue<>();
expressLane.add(new Customer("Harry"));
在API文檔中,會發現另外一組名字以Abstract開頭的類,例如,AbstractQueue,這是集合框架中的爲類庫實現者而設計的。如果想自己實現自己的隊列類,會發現拓展AbstractQueue類要比實現Queue接口中的所有方法輕鬆的多。
Part2:Collection接口和迭代器:
在Java類庫中,集合類的基本接口是Collection接口。這個接口有兩個基本方法:
public interface Collection<E>
{
boolean add(E element);
Iterator<E> iterator();
...
}
add方法顧名思義,而迭代器方法則是用於返回一個實現了Iterator接口的對象。可以使用這個迭代器對象依次訪問集合中的元素!
Iterator接口包含四個方法:
public interface Iteratoe<E>
{
E next();
boolean hasNext();
void remove();
default void forEachRemanining(Consumer<? super E>action);
}
通過反覆調用next方法,可以逐個訪問集合中的每個元素。但是,如果到達了集合的末尾,next方法將拋出一個NoSuchElementException異常。因此,需要在使用next方法之前,使用hasnext方法。
Collection<String> c = ...;
Iterator<String> iter = c.iterator();
while(iter.hasNext())
{
String element = iter.next();
//code....
}
還可以用for…each循環可以更加簡練的表示同樣的循環操作:
for(String element : c)
{
do something with element;
}
編譯器簡單地將“for each”循環翻譯爲帶有迭代器的循環。
“for each”循環可以與任何實現了Iterable接口的對象一起工作,這個接口只包含一個抽象方法:
public interface Iterable<E>
{
Iterator<E> iterator();
...
}
Collection接口拓展了Iterable接口。因此,對於標準類庫中的任何集合都可以使用”for each”循環。
在Java的迭代器中,查找操作與位置變更是緊密相連的。查找一個元素唯一的方法是調用next,而執行查找操作的同時,迭代器位置會隨之向前移動。
因此,應該將Java迭代器認爲是位於兩個元素之間。當調用next時,迭代器就越過下一個元素,並返回剛剛越過的那個元素的引用。
Iterator接口的remove方法將會刪除上次調用的next方法時返回的元素。
更重要的是,next方法和remove方法的調用具有互相依賴性。 如果調用remove之前,沒有調用next將是不合法的。那樣做,將會拋出一個IllegalStateEception的異常!