簡(jiǎn)介
Java最初版本只實(shí)現(xiàn)了一些常用的數(shù)據(jù)結(jié)構(gòu)蒿辙,并提供了這些類(lèi)或接口Vector,Stack,Hashtable,BitSet,Enumeration接口來(lái)實(shí)現(xiàn)這些結(jié)構(gòu)匾七。
其中Enumeration接口提供了讓我們能枚舉任意容器元素的抽象機(jī)制汇恤。
特點(diǎn)
將集合的接口與實(shí)現(xiàn)分離
這一點(diǎn)我們可以從常見(jiàn)的隊(duì)列Queue的設(shè)計(jì)上看出來(lái)偶器,隊(duì)列的原則是尾部添加元素略号,在隊(duì)列的頭部刪除元素,可以看到Java的實(shí)現(xiàn)是首先定義了一個(gè)接口刻肄,里面定義了一些Queue的常用操作方法,
public interface Queue<E> extends Collection<E> {
...
boolean add(E e);
boolean offer(E e);
E remove();
...
}
然后在根據(jù)不同的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)隊(duì)列采够,通常情況下隊(duì)列使用兩種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)肄方,循環(huán)數(shù)組和鏈表,如下圖:
這樣在編程的時(shí)候只需要更換實(shí)現(xiàn)類(lèi)就可以輕松的切換所使用的數(shù)據(jù)結(jié)構(gòu)了蹬癌。
Collection
可以看到上面的Queue都繼承Collection权她,其實(shí)集合類(lèi)的都是繼承了他,他提供了幾個(gè)最基本的方法:
public interface Collection<E> extends Iterable<E> {
boolean add(E e);
Iterator<E> iterator();
}
當(dāng)然還有其他方法逝薪。
add:添加一個(gè)元素
iterator:返回一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象隅要。使用它可以很方便的訪問(wèn)集合中的元素。
Iterator
Iterator接口包含的方法:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
遍歷元素的方式通過(guò)反復(fù)調(diào)用next方法即可訪問(wèn)每個(gè)元素董济,但是如果達(dá)到了集合末尾步清,將拋出NoSuchElementException,所以在調(diào)用next方法前要先調(diào)用hasNext方法檢測(cè)虏肾。
ArrayList<String> strings = new ArrayList<>();
strings.add("a");
strings.add("b");
strings.add("c");
strings.add("d");
strings.add("e");
Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
當(dāng)然也可以通過(guò)foreach循環(huán)遍歷:
for (String s :
strings ) {
System.out.println(s);
}
編譯器會(huì)把for each語(yǔ)法結(jié)構(gòu)轉(zhuǎn)為上面的迭代器的結(jié)構(gòu)廓啊。這種方式可以遍歷所有實(shí)現(xiàn)了Iterable接口的結(jié)構(gòu)。
Iterable
Iterable只包含一個(gè)iterator抽象方法
public interface Iterable<T> {
Iterator<T> iterator();
...
}
目的是讓用戶實(shí)現(xiàn)自定義的數(shù)據(jù)結(jié)構(gòu)返回一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象封豪,我們看到ArrayList的實(shí)現(xiàn)如下:
public Iterator<E> iterator() {
return new Itr();
}
其中Itr是一個(gè)內(nèi)部類(lèi)谴轮,定義在ArrayList中,并實(shí)現(xiàn)了Iterator接口吹埠。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
最重要的是Java SE8中不寫(xiě)循環(huán)而直接使用forEachRemaining方法就可以使用Lambda表達(dá)式處理每個(gè)元素:
strings.iterator().forEachRemaining(e-> System.out.println(e));
同時(shí)也可是使用Iterable接口中的forEach方法來(lái)遍歷:
strings.forEach(e-> System.out.println(e));