-
接口中仅定义行为,接口方法是对多个类的某种行为的抽象。
-
接口中的方法是为了供外部访问的,因此都必须是外部可访问的、即必须是全局的即public的。
-
仅允许且必须将供外部访问的方法定义在接口中,以供外部访问。
-
类中定义数据,类中数据是对对象的状态的抽象。
-
类中的方法除了其所实现的接口方法外,都只能是为外部可访问的接口方法提供支持的,都必须是非public的,可以是protected、default,或者private。
-
类中实现的接口方法,都是个性化的、是通过操作类中定义的数据来实现的。
接口 java.lang.Iterable
javadoc:
所有实现了java.lang.Iterable接口的类对象,都可以被应用for-each loop语句。
建议使用 for-each loop 遍历此接口的类对象,除非需要对元素做更新(增加、删除)操作。
public interface Iterable<T>{
default void foreach(Consumer<T> consumer){
for (T t : this) { // for-each loop
consumer.accept(t);
}
}
Iterator<T> iterator();
}
接口 java.util.Iterator
迭代器:开发者通过调用next()接口方法,可以遍历集合中所有元素、可以更新元素的数据、也可以remove()移除元素。
public interface Iterator<T>{
boolean hasNext();
T next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
java.util.Collection
Collection接口继承了Iterable接口
public interface Collection<E> implements Iterable<E>{
...
Iterator<E> iterator();
...
}
各个Collection实现类对Iterable接口的实现
要记住,接口方法仅是对行为的抽象定义,类中的方法则是对数据进行操作、对接口中定义的行为进行个性化实现。因此两者的差别就在于——数据。接口仅定义行为;类中则会定义数据,并在具体方法中操作数据,用于实现接口中定义的行为。
换一种说法,就是所有接口中定义的行为、方法,都是对数据操作的抽象,因此接口的实现离不开数据状态的定义和操作。
在Iterable接口的各个实现类中,都定义了一个实现了Iterator接口的内部类,并在iterator()接口方法中创建并返回一个这个内部类的实例。
之所以将对Iterator接口的实现类定义为内部类,是因为这个实现类中的方法操作的正是外部类中定义的数据,并且需要大量调用外部类中的方法(这正是需要定义内部类的常见情形:当内部类与外部类需要紧密协作时)。在这个内部类中也单独定义了一些变量,这些变量只被Iterator接口方法操作,外部类中没有需要操作这些数据的方法,因此仅定义在内部类中。
以下对各个实现类的分析,都是在阐释上述结论。
ArrayList对Iterable接口的实现
ArrayList中首先定义了要操作的数据:Object[] elementData;
以及数据的属性:size;
接着开始对数据操作,即实现接口中的方法。
在实现Iterable接口的iterator()方法时,由于其需要返回一个Iterator接口实例,鉴于这个接口中的方法操作的正是ArrayList类中定义的数据elementData,并需要调用ArrayList类的方法,因此直接定义了一个内部类 Itr<E> implements Iterator<E>
,而这个内部类中方法的实现又需要另外一些变量的支持,将这些仅与Iterator接口方法的数据操作的实现有关的变量定义在这个内部类中,这些变量不会被外部类的方法操作到。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable{
transient Object[] elementData; // 定义要操作的数据
private int size; // 定义数据的一些属性
...
public boolean add(E e){ // 定义对数据的操作,即实现Collection接口中定义的add方法
}
public Iterator<E> iterator() { // 定义对数据的操作,实现Iterable接口的iterator()方法
return new Itr(); // 定义内部类实现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;
Itr() {}
public boolean hasNext() {
return cursor != size; // 外部类的状态数据(size)+内部类的状态数据(cursor)共同支撑接口方法
}
@SuppressWarnings("unchecked")
public E next() { // 外部类的状态数据(elementData)+内部类的状态数据(cursor)共同支撑接口方法
checkForComodification();
int i = cursor;
if (i >= ArrayList.this.size) // 直接使用外部类的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();
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
}
...
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
}
Map<K,V>接口与Iterable<E>接口
Map<K,V>接口并未直接实现Iterable<E>接口,不过Map接口中有几个方法的返回值类型继承了Iterable接口:Set<K> keySet();
、Collection<V> values();
以及Set<Entry<K,V>> entrySet()
。因此Map<K,V>接口的实现类在实现这些方法时,也必须确保方法的返回值对象能被应用iterator()方法、并能得到一个Iterator实例对象。
为此,Map<K,V>的实现类内部也定义了相应的数个Iterator接口的实现类。
下面让我们来看一看Map<K,V>的实现类HashMap<K,V>是如实现keySet()方法并定义这个的返回值的。
HashMap<K,V>对Iterable<E>接口的实现
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{
/**
* 定义要操作的数据 的部分数据结构——桶,将K-V键值对用拉链法连接构造成一个桶:
*/
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key; // 要操作的数据-键值对的key值
V value; // 要操作的数据-键值对的value值
Node<K,V> next; // 构建前后节点之间的链
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
...
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
...
}
transient Node<K,V>[] table; // 定义Map<K,V>接口方法要操作的数据整体
transient Set<Map.Entry<K,V>> entrySet; // 定义需要遍历K-V键值对时用到的变量
transient int size; // 定义数据的属性
transient int modCount; // 定义用于快速迭代失败的属性
...
public V put(K key, V value) { // 定义操作数据的方法,即实现Map<K,V>接口的put方法
return putVal(hash(key), key, value, false, true);
}
public Set<K> keySet() { // 定义获取key集-keySet的方法,返回值类型Set<K>必须是一个
Set<K> ks = this.keySet;
if (ks == null) {
ks = new KeySet(); // 创建一个内部类KeySet的实例
this.keySet = ks;
}
return ks;
}
// 定义一个Set<K>接口的实现类——内部类KeySet——用于实现keySet()操作,返回Map的K集,并实现对K集的操作接口
final class KeySet extends AbstractSet<K> {
// 实现Iterator接口的iterator()方法,专门为此方法定义了一个内部类KeyIterator
public final Iterator<K> iterator() { return new KeyIterator(); }
// 以下方法都是对Map的K集的操作,都是直接调用HashMap的方法支持
public final int size() { return HashMap.this.size; }
public final void clear() { HashMap.this.clear(); }
public final boolean contains(Object o) { return HashMap.this.containsKey(o); }
public final boolean remove(Object key) {
return HashMap.this.removeNode(hash(key), key, null, false, true) != null;
}
public final void forEach(Consumer<? super K> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
// 定义了一些仅用于支撑Iterator接口方法的变量
abstract class HashIterator {
Node<K,V> next; // next entry to return
Node<K,V> current; // current entry
int expectedModCount; // for fast-fail
int index; // current slot
HashIterator() {
expectedModCount = HashMap.this.modCount;
Node<K,V>[] t = HashMap.this.table;
current = next = null;
index = 0;
if (t != null && HashMap.this.size > 0) { // 找到第一个有数据的桶,
do {} while (index < t.length && (next = t[index++]) == null);
}
}
public final boolean hasNext() {
return next != null;
}
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = this.next;
if (HashMap.this.modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
...
}
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
final class ValueIterator extends HashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
}
LinkedHashMap<K,V>对HashMap的实现
HashSet<T>对Iterable<T>接口的实现
HashSet<T>类内定义了一个HashMap<K,V>对象用于存储要操作的数据,因此HashSet<T>中的接口方法实际是对HashMap<K,V>进行操作,结果就是其所有接口方法都是直接调用HashMap<K,V>的方法来实现,包括其实现的Iterable接口的iterater()方法。
public class HashSet<T\> extends AbstractSet<T\> implements Set<T> , Cloneable, Serializable{
private transient HashMap<T,Object> map; // 将要操作的数据存储在map的Key中。
public HashSet() {
map = new HashMap<>();
}
public Iterator<E> iterator() { // 直接调用map的方法
return map.keySet().iterator();
}
public int size() {
return map.size();
}
}