Java源码解析HashMap的keySet()方法
Java中的HashMap提供了一个keySet()方法,该方法用于获取HashMap中的key的集合。下面我们将对HashMap的keySet()方法进行源码解析,以了解其内部实现机制。
看一下keySet()方法的代码:
```java
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
```
从代码中可以看到,第一次调用keySet方法时,keySet属性是null,然后进行了初始化,再将keySet属性返回。这也就是说,HashMap里并不会随着put和remove的进行维护一个keySet集合,而是在第一次调用keySet方法时,才给keySet属性初始化。
那么,HashMap的key是什么时候加入到keySet集合中的呢?答案是,在遍历的时候,使用迭代器对key进行的遍历。下面我们看一下KeySet类的代码:
```java
final class KeySet extends AbstractSet<K> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<K> iterator() { return new KeyIterator(); }
public final boolean contains(Object o) { return containsKey(o); }
public final boolean remove(Object key) { return removeNode(hash(key), key, null, false, true) != null; }
public final Spliterator<K> spliterator() { return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0); }
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;
...
}
}
}
}
```
可以看到,KeySet类中的迭代器函数,返回的是一个KeyIterator类的对象。它的next方法返回的是HashIterator的nextNode的key。也就是说,当使用迭代器遍历set内的元素时,KeySet类的迭代器,会保证能够依次获取到HashMap的节点的key值,这就是我们遍历keySet的过程的实质。
HashMap的keySet()方法并不是在添加和删除元素时维护一个keySet集合,而是在第一次调用keySet方法时,进行初始化,然后使用迭代器遍历HashMap的key值。