要分析的Java程序
先上代码:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(100, "aa");
map.put(200, "bb");
map.put(300, "cc");
Set<Entry<Integer, String>> ss = map.entrySet();
for(Iterator<Entry<Integer, String>> iter = ss.iterator(); iter.hasNext();) {
Entry<Integer, String> temp = iter.next();
System.out.println(temp.getKey() + "---" + temp.getValue());
}
}
}
输出结果:
100---aa
200---bb
300---cc
entrySet方法的源码分析
Map是一个接口:
public interface Map<K,V> {......}
Map接口有一个entrySet方法:
Set<Map.Entry<K, V>> entrySet();
接口里定义的方法只能是抽象方法、类方法、默认方法或私有方法,因此如果不是定义默认方法、类方法或私有方法,系统将自动为普通方法增加abstract修饰符;定义接口里的普通方法时不管是否使用public abstract修饰符,接口里的普通方法总是使用public abstract来修饰。接口里的普通方法不能有方法实现(方法体);但类方法、默认方法、私有方法都必须有方法实现(方法体)。
所以Map接口里面的entrySet方法是一个抽象方法,没有方法体。
HashMap类实现了Map接口:
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {......}
所以HashMap类必须实现Map接口的entrySet方法:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
他返回一个Set集合,里面存放的元素的类似是Map.Entry<K,V>。
Map接口里面有Entry接口:
interface Entry<K,V> {......}
内部接口也被称为嵌套接口,这意味着在另一个接口内声明一个接口。
Entry接口是Map接口的内部接口。
HashMap类里面有table数组:
transient Node<K,V>[] table;
table就是HashMap的核心数组结构,我们也称之为“位桶数组”(往里面装东西的)。
Node是HashMap类的静态内部类,他实现了Map.Entry接口:
static class Node<K,V> implements Map.Entry<K,V> {......}
所以HashMap类的entrySet方法就是返回一个Set集合,里面放的是一个个键值对。
getKey方法和getValue方法的源码分析
一开始的代码,打印的时候,调用了getKey方法和getValue方法,这是Map接口里面的内部接口Entry的方法。
interface Entry<K,V> {
K getKey();
V getValue();
......
}
Map接口的实现类HashMap类的静态内部类Node实现了Map接口的内部接口Entry,
所以Node就要实现getKey方法和getValue方法:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
......
}
iterator方法的源码分析
Set接口继承了Collection接口:
public interface Set<E> extends Collection<E> {......}
Collection接口继承了Iterable接口:
public interface Collection<E> extends Iterable<E> {......}
Iterable接口定义了一个抽象方法iterator:
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
......
}
iterator方法返回Iterator接口:
public interface Iterator<E> {......}
Iterator接口里面有这些抽象方法:
打开断点调试,发现变量ss的类型是HashMap类的内部类EntrySet:
因为HashMap类的entrySet方法里面会向上转型:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
其中,EntrySet是HashMap类的内部类,里面实现了iterator方法:
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
所以一开始的代码中,ss.iterator(),调用的是HashMap类的内部类EntrySet实现的iterator方法。