keyset
的使用和实现
keyset可以获取Map中所有的key值,查看keyset
方法。
KeySet是HashMap的内部类,在keyset
方法中返回KeySet实例,没有添加key元素;
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
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; 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();
}
}
}
通过编译keyset的使用方法,查看keyset的本质;
public class MapTest {
public static void main(String[] args)
{
Map<String, String> map = new HashMap<String, String>();
map.put("1","uranus");
map.put("2", "leon");
Set<String> ks = map.keySet();
for (String s : ks)
{
System.out.println(s);
}
}
}
使用jad编译上述代码,jad .\MapTest.class
。从编译后代码可以看出,keyset的使用是通过iterator获取所有键值。
public class MapTest
{
public MapTest()
{
}
public static void main(String args[])
{
Map map = new HashMap();
map.put("1", "uranus");
map.put("2", "leon");
Set ks = map.keySet();
String s;
for(Iterator iterator = ks.iterator(); iterator.hasNext(); System.out.println(s))
s = (String)iterator.next();
}
}
查看类KeySet
中的迭代器,返回外部类HashMap中的KeyIterator
类。
public final Iterator<K> iterator() { return new KeyIterator(); }
查看KeyIterator
类,继承了HashIterator
类。
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
查看HashIterator
类
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 = modCount;
Node<K,V>[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
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 = next;
if (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;
}
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}
}