zoukankan      html  css  js  c++  java
  • java中HashMap的keySet()和values()

        我们通常说,keySet()返回所有的键,values()返回所有的值,其实是不太对的,因为无论是keySet()和values(),其实都没有实质的内容,且容我慢慢说来。

       他们前者返回了一个Set,后者返回了一个Collection,但是Set和Collection都只是接口,既然是接口,那就大有文章可以做。很重要的一点就是,接口可以不是new someClass()的来的,也就是说,它可以不对应与一个类,而只提供一些方法。实际上,HashMap中所有的数据都是放在一个Node<E,V>[]的数组中的,而返回的Set接口也好,Collection也罢,都是直接针对这个Node<E,V>[]数组的,所以,当使用返回的Set接口或者Collection接口进行操作是,实际上操作的还是那个Node<E,V>[]数组。但是,返回的Collection只能做有限的操作,限定哪些呢?一句话总结就是:只能读,不能写,但能删能清。

    不信?我们可以看源码。

    首先来看values方法:

    public Collection<V> values() {
            Collection<V> vs = values;
            if (vs == null) {
                vs = new Values();
                values = vs;
            }
            return vs;
        }

    可以看到values其实是返回了一个Values类的,这是个内部类,就在它后面:

        final class Values extends AbstractCollection<V> {
            public final int size()                 { return size; }
            public final void clear()               { HashMap.this.clear(); }
            public final Iterator<V> iterator()     { return new ValueIterator(); }
            public final boolean contains(Object o) { return containsValue(o); }
            public final Spliterator<V> spliterator() {
                return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
            }
            public final void forEach(Consumer<? super V> 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.value);
                    }
                    if (modCount != mc)
                        throw new ConcurrentModificationException();
                }
            }
        }

    看到没有,完全没有提供新数据,完全是操作那个table,或者调用hashMap自己的方法。我之前傻呵呵的找源码是怎么为values(HashMap除了有values这个方法,还有一个属性也叫values,坑爹不?)赋值的,现在才知道自己是这么傻,因为根本就没有复制嘛。

    再来看keySet,也是一样的思路:

     1     public Set<K> keySet() {
     2         Set<K> ks = keySet;
     3         if (ks == null) {
     4             ks = new KeySet();
     5             keySet = ks;
     6         }
     7         return ks;
     8     }
     9 
    10     final class KeySet extends AbstractSet<K> {
    11         public final int size()                 { return size; }
    12         public final void clear()               { HashMap.this.clear(); }
    13         public final Iterator<K> iterator()     { return new KeyIterator(); }
    14         public final boolean contains(Object o) { return containsKey(o); }
    15         public final boolean remove(Object key) {
    16             return removeNode(hash(key), key, null, false, true) != null;
    17         }
    18         public final Spliterator<K> spliterator() {
    19             return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    20         }
    21         public final void forEach(Consumer<? super K> action) {
    22             Node<K,V>[] tab;
    23             if (action == null)
    24                 throw new NullPointerException();
    25             if (size > 0 && (tab = table) != null) {
    26                 int mc = modCount;
    27                 for (int i = 0; i < tab.length; ++i) {
    28                     for (Node<K,V> e = tab[i]; e != null; e = e.next)
    29                         action.accept(e.key);
    30                 }
    31                 if (modCount != mc)
    32                     throw new ConcurrentModificationException();
    33             }
    34         }
    35     }
  • 相关阅读:
    ZendStudio 解决svn导出项目乱码问题
    Linux常用命令
    php类与对象
    Apache shutdown unexpectedly启动错误解决方法
    php构造函数和析构函数
    MySQL基本概念
    Javascript中常用事件的命名
    网页布局
    页面的自动滚动效果
    表单验证和事件(2)
  • 原文地址:https://www.cnblogs.com/JMLiu/p/7763885.html
Copyright © 2011-2022 走看看