集合的接口与实现分离
与现代的数据结构类库的常见情况一样,Java 集合类库也将接口(interface)与实现(implementation)分离。
Collection 接口
在 Java 类库中,集合类的基本接口是 Collection 接口。除了 Map 的接口是 Map。
迭代器
集合类使用迭代器(Iterator)来访问集合的每个元素。Iterator 接口包含 4 个方法:
public interface Iterator<E> {E nexe();boolean hasNext();default void remove();default void forEachRemaining(Consumer<? super E> action);}
可以直接调用集合的 iterator() 来得到迭代器从而迭代集合:
Collection<String> c = ...Iterator<String> iter = c.iterator();while(iter.hasNext()) {String element = iter.next();System.out.println(element);}
Java 封装了 for each 语句来让你更方便的迭代集合元素:
for (String element : c) {System.out.println(element);}
其实 Java 编译器并不知道如何遍历集合原始。上述代码能够编译通过,只是因为编译器把 for each 循环通过 Iterator 改写为了循环:
// forfor (Iterator<String> iter = c.iterator(); iter.hasNext(); ) {String element = iter.next();System.out.println(element);}// whileIterator<String> iter = c.iterator();while(iter.hasNext()) {String element = iter.next();System.out.println(element);}
可以看到,在 Iterator 中还有一个 forEachRemaining() ,它可以和 lambda 表达式结合,遍历集合元素:
list.iterator().forEachRemaining(element -> System.out.println(element));
在 Java 中,应该理解迭代器在两个元素之间。调用 next(),迭代器就越过下个元素,并返回越过那个元素的引用。这一点在使用 remove() 方法时应该深有体会。remove() 会删除上次调用 next() 方法时返回的元素:
Iterator<String> it = c.iterator();it.remove(); // 不能直接调用 remove(),因为此时的 it 还未接受 next 传来的对象Iterator<String> it = c.iterator();it.next();it.remove(); // OKIterator<String> it = c.iterator();it.next();it.remove();it.remove(); // 连续调用将会抛出 IllegalStateException 异常,因为上一个 remove() 已经将 it 中 next 传来的对象移除Iterator<String> it = c.iterator();it.next();it.remove(); // OKit.next();it.remove(); // OK
集合框架中的接口
Java集合框架为不同类型的集合定义了大量接口:
