java核心技術卷I-集合框架

Java集合框架

與現代的數據結構類庫的常見情況一樣, Java 集合類庫也將接口(interface) 與 實 現(implementation) 分離

隊列 (queue)

隊列接口指出可以在隊列的尾部添加元素, 在隊列的頭部刪除元素,並且可以査找隊列中元素的個數。當需要收集對象, 並按照“ 先進先出” 的規則檢索對象時就應該使用隊列

public interface Queue<E> // a simplified form of the interface in the standard library
{
	void add(E element);
	E remove();
	int size();
}

這個接口並沒有說明隊列是如何實現的。隊列通常有兩種實現方式: 一種是使用循環數組;另一種是使用鏈表。

Collection接口

在 Java 類庫中,集合類的基本接口是 Collection 接口。這個接口有兩個基本方法

public interface Collection<E>
{
	boolean add(E element);
	Iterator<E> iterator();
...
}

add方法用於向集合中添加元素。如果添加元素確實改變了集合就返回 true, 如果集合沒有發生變化就返回 false。
iterator方法用於返回一個實現了 Iterator 接口的對象。可以使用這個迭代器對象依次訪問集合中的元素。

迭代器

Iterator接口包含4個方法:

public interface Iterator<E>
{
	E next();
	boolean hasNext();
	void remove();
	default void forEachRemaining(Consumer<? super E> action);
}

通過反覆調用 next 方法,可以逐個訪問集合中的每個元素。但是,如果到達了集合的末尾,next 方法將拋出一個 NoSuchElementException。 因此,需要在調用 next 之前調用 hasNext方法。如果迭代器對象還有多個供訪問的元素, 這個方法就返回 true。如果想要査看集合中的所有元素,就請求一個迭代器,並在 hasNext 返回 true 時反覆地調用 next 方法。

Collection<String> c = . . .;
Iterator<String> iter = c.iterator();
while (iter.hasNext())
{
	String element = iter.next();
	//do something with element
}

用“ for each” 循環可以更加簡練地表示同樣的循環操作:
for (String element : c)
{
//do something with element
}
Collection接口擴展了 Iterable 接口。因此,對於標準類庫中的任何集合都可以使用“ for
each” 循環。
在 Java SE 8中,甚至不用寫循環。可以調用 forEachRemaining 方法並提供一 lambda表達式(它會處理一個元素)。 將對迭代器的每一個元素調用這個 lambda 表達式,直到再沒有元素爲止。
元素被訪問的順序取決於集合類型。 如果對 ArrayList 進行迭代, 迭代器將從索引 0開始,每迭代一次,索引值加 U 然而,如果訪問 HashSet 中的元素, 每個元素將會按照某種隨機的次序出現。雖然可以確定在迭代過程中能夠遍歷到集合中的所有元素,但卻無法預知元素被訪問的次序。這對於計算總和或統計符合某個條件的元素個數這類與順序無關的操作來說,並不是什麼問題。
Java 迭代器查找操作與位置變更是緊密相連的。查找一個元素的唯一方法是調用 next, 而在執行查找操作的同時, 迭代器的位置隨之向前移動,應該將 Java 迭代器認爲是位於兩個元素之間。 當調用 next 時,迭代器就越過下一個元素,並返回剛剛越過的那個元素的引用。
Iterator 接口的 remove 方法將會刪除上次調用 next 方法時返回的元素。

it.next(); // skip over the first element
it. remove(); // now remove it

集合框架中的接口

集合有兩個基本接口:Collection 和 Map。 我們已經看到,可以用以下方法在集合中插人元素:

boolean add(E element)

不過,由於映射包含鍵 / 值對,所以要用 put 方法來插人:

V put(K key, V value)

要從集合讀取元素, 可以用迭代器訪問元素。不過,從映射中讀取值則要使用 get 方法:

V get(K key)

List

List 是一個有序集合。元素會增加到容器中的特定位置。可以採用兩種方式訪問元素:使用迭代器訪問, 或者使用一個整數索引來訪問。後一種方法稱爲隨機訪問(random access ), 因爲這樣可以按任意順序訪問元素。與之不同, 使用迭代器訪問時,必須順序地訪問元素
List 接口定義了多個用於隨機訪問的方法:

void add(int index, E element)
void remove(int index)
E get(int index)
E set(int index, E element)

坦率地講,集合框架的這個方面設計得很不好。實際中有兩種有序集合,其性能開銷有
很大差異。由數組支持的有序集合(ArrayList)可以快速地隨機訪問,因此適合使用 List 方法並提供一個整數索引來訪問。與之不同, 鏈表(LinkedList)儘管也是有序的, 但是隨機訪問很慢,所以最好使用迭代器來遍歷。如果原先提供兩個接口就會容易一些了。

Set

Set 接口等同於 Collection 接口,不過其方法的行爲有更嚴謹的定義。集(set) 的 add方法不允許增加重複的元素。要適當地定義集的 equals 方法:只要兩個集包含同樣的元素就認爲是相等的,而不要求這些元素有同樣的順序。hashCode 方法的定義要保證包含相同元素的兩個集會得到相同的散列碼。
SortedSet 和 SortedMap 接口會提供用於排序的比較器對象,這兩個接口定義了可以得到集合子集視圖的方法。
最後,Java SE 6 引人了接口 NavigableSet 和 NavigableMap, 其中包含一些用於搜索和遍歷有序集和映射的方法。(理想情況下,這些方法本應當直接包含在 SortedSet 和 SortedMap接口中)。TreeSet 和 TreeMap 類實現了這些接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章