`keyset`的使用和实现

keyset的使用和实现
  • HashMap(2): EntrySet、KeySet实现原理
  • HashMap中keySet()底层调用解析

keyset可以获取Map中所有的key值,查看keyset方法。

KeySet是HashMap的内部类,在keyset方法中返回KeySet实例,没有添加key元素;

public Set keySet() {
    Set ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

final class KeySet extends AbstractSet {
    public final int size()                 { return size; }
    public final void clear()               { HashMap.this.clear(); }
    public final Iterator 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 spliterator() {
        return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer action) {
        Node[] 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 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 map = new HashMap();

        map.put("1","uranus");
        map.put("2", "leon");

        Set 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 iterator()     { return new KeyIterator(); }

查看KeyIterator类,继承了HashIterator类。

final class KeyIterator extends HashIterator
    implements Iterator {
    public final K next() { return nextNode().key; }
}

查看HashIterator

abstract class HashIterator {
    Node next;        // next entry to return
    Node current;     // current entry
    int expectedModCount;  // for fast-fail
    int index;             // current slot

    HashIterator() {
        expectedModCount = modCount;
        Node[] 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 nextNode() {
        Node[] t;
        Node 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 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;
    }
}

你可能感兴趣的:(`keyset`的使用和实现)