zoukankan      html  css  js  c++  java
  • 走进JDK(九)------AbstractMap

    map其实就是键值对,要想学习好map,得先从AbstractMap开始。

    一、类定义、构造函数、成员变量

    public abstract class AbstractMap<K,V> implements Map<K,V>
    protected AbstractMap() {
    }

    这是个抽象类,很明显只是为子类们提供一些共用的方法模板。

    成员变量:

        transient Set<K>        keySet;//说明abstractMap中的key是不允许重复的
    transient Collection<V> values;//value当然可以重复
        //map当中的实体,代表一个键值对
        public abstract Set<Entry<K,V>> entrySet();
        public static class SimpleEntry<K,V> implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = -8499721149061103585L;
            private final K key;
            private V value;
    
            public SimpleEntry(K key, V value) {
                this.key   = key;
                this.value = value;
            }
    
            public SimpleEntry(Entry<? extends K, ? extends V> entry) {
                this.key   = entry.getKey();
                this.value = entry.getValue();
            }
    
            public K getKey() {
                return key;
            }
    
            public V getValue() {
                return value;
            }
    
            public V setValue(V value) {
                V oldValue = this.value;
                this.value = value;
                return oldValue;
            }
    
            public boolean equals(Object o) {
                if (!(o instanceof Map.Entry))
                    return false;
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                return eq(key, e.getKey()) && eq(value, e.getValue());
            }
    
            public int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
            public String toString() {
                return key + "=" + value;
            }
    
        }

    二、主要方法

    1、size()

        public int size() {
            //返回entry的数量
            return entrySet().size();
        }

    2、isEmpty()

        public boolean isEmpty() {
            //判断entry数量是否为0
            return size() == 0;
        }

    3、containsValue()、containsKey()

        public boolean containsValue(Object value) {
            //entrySet循环,因为是个set,所以可用iterator,set后面的博文介绍
            Iterator<Entry<K,V>> i = entrySet().iterator();
            //这个问题已经解释很多次了,判断非null主要就是为了防止使用equals()报错。而且很多不同子类就会重写object父类的equals方法,例如Stirng的equals(),所以为null的时候就比较内存地址,不为null就调用value具体equals(),例如string就是判断字符串是否相等
            if (value==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getValue()==null)
                        return true;
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (value.equals(e.getValue()))
                        return true;
                }
            }
            return false;
        }
        //此方法与上面方法没啥差别,只是一个比较value,一个比较key
        public boolean containsKey(Object key) {
            Iterator<Map.Entry<K,V>> i = entrySet().iterator();
            if (key==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        return true;
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        return true;
                }
            }
            return false;
        }

    4、get()

        //此方法也很简单,没啥说的。。。
        public V get(Object key) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (key==null) {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        return e.getValue();
                }
            } else {
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        return e.getValue();
                }
            }
            return null;
        }

    5、put()、putAll()

        public V put(K key, V value) {
            //由子类实现,父类不提供具体的操作逻辑
            throw new UnsupportedOperationException();
        }
        public void putAll(Map<? extends K, ? extends V> m) {
            //循环要加入的map的entry,然后将键值对加入到当前map中
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
                put(e.getKey(), e.getValue());
        }

    6、remove()、clear()

        public V remove(Object key) {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            Entry<K,V> correctEntry = null;
            if (key==null) {
                while (correctEntry==null && i.hasNext()) {
                    Entry<K,V> e = i.next();
                    //如果map中的key为null
                    if (e.getKey()==null)
                        //这地方是为了退出循环
                        correctEntry = e;
                }
            } else {
                while (correctEntry==null && i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        correctEntry = e;
                }
            }
    
            V oldValue = null;
            if (correctEntry !=null) {
                oldValue = correctEntry.getValue();
                //由于上面循环到了当前entry并赋值给了correctEntry,因此调用remove()删除的就是此entry
                i.remove();
            }
            return oldValue;
        }
        //清除所有的entry
        public void clear() {
            entrySet().clear();
        }

    7、keySet()

        //获取当前map中的所有key,并放到set中
        public Set<K> keySet() {
            Set<K> ks = keySet;
            //如果之前有调用过keySet方法,则直接给出所有的key
            if (ks == null) {            
                //内部使用了AbstractSet,并且还弄了个匿名内部类也就是AbstractSet啦。其实本质上就相当于编写一个子类继承AbstractCollection,并且实现了hasNext()、next()等方法。

    然后将entrySet.iterator赋值给当前的set,等到后面使用的时候,再去取所有的key
                ks = new AbstractSet<K>() {
                    public Iterator<K> iterator() {
                        return new Iterator<K>() {
                            //拿到所有的entry
                            private Iterator<Entry<K,V>> i = entrySet().iterator();
    
                            public boolean hasNext() {
                                return i.hasNext();
                            }
    
                            public K next() {
                                return i.next().getKey();
                            }
    
                            public void remove() {
                                i.remove();
                            }
                        };
                    }
    
                    public int size() {
                        return AbstractMap.this.size();
                    }
    
                    public boolean isEmpty() {
                        return AbstractMap.this.isEmpty();
                    }
    
                    public void clear() {
                        AbstractMap.this.clear();
                    }
    
                    public boolean contains(Object k) {
                        return AbstractMap.this.containsKey(k);
                    }
                };
                keySet = ks;
            }
            return ks;
        }

    8、values()

        //这个类跟keySet本质上是一回事,就是编写一个子类继承AbstractCollection,并且实现了hasNext()、next()等方法
        public Collection<V> values() {
            Collection<V> vals = values;
            if (vals == null) {
                vals = new AbstractCollection<V>() {
                    public Iterator<V> iterator() {
                        return new Iterator<V>() {
                            private Iterator<Entry<K,V>> i = entrySet().iterator();
    
                            public boolean hasNext() {
                                return i.hasNext();
                            }
    
                            public V next() {
                                return i.next().getValue();
                            }
    
                            public void remove() {
                                i.remove();
                            }
                        };
                    }
    
                    public int size() {
                        return AbstractMap.this.size();
                    }
    
                    public boolean isEmpty() {
                        return AbstractMap.this.isEmpty();
                    }
    
                    public void clear() {
                        AbstractMap.this.clear();
                    }
    
                    public boolean contains(Object v) {
                        return AbstractMap.this.containsValue(v);
                    }
                };
                values = vals;
            }
            return vals;
        }

     9、equals()、hashCode()、toString()、clone()

        public boolean equals(Object o) {
            if (o == this)
                return true;
            //不为map肯定不相等了
            if (!(o instanceof Map))
                return false;
            Map<?,?> m = (Map<?,?>) o;
            //长度不相等也没啥好比的
            if (m.size() != size())
                return false;
    
            try {
                Iterator<Entry<K,V>> i = entrySet().iterator();
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    K key = e.getKey();
                    V value = e.getValue();
                    //当value为null时
                    if (value == null) {
                        //比较对象的value为null并且包含相同的key,否则不相等
                        if (!(m.get(key)==null && m.containsKey(key)))
                            return false;
                    } else {
                        //value不为null时,直接拿比较对象的key取m中取value值,如果value不为null,说明key存在,然后判断value即可
                        if (!value.equals(m.get(key)))
                            return false;
                    }
                }
            } catch (ClassCastException unused) {
                return false;
            } catch (NullPointerException unused) {
                return false;
            }
    
            return true;
        }
        public int hashCode() {
            int h = 0;
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext())
                h += i.next().hashCode();
            return h;
        }
        public String toString() {
            Iterator<Entry<K,V>> i = entrySet().iterator();
            if (! i.hasNext())
                return "{}";
    
            StringBuilder sb = new StringBuilder();
            sb.append('{');
            for (;;) {
                Entry<K,V> e = i.next();
                K key = e.getKey();
                V value = e.getValue();
                sb.append(key   == this ? "(this Map)" : key);
                sb.append('=');
                sb.append(value == this ? "(this Map)" : value);
                if (! i.hasNext())
                    return sb.append('}').toString();
                sb.append(',').append(' ');
            }
        }
        protected Object clone() throws CloneNotSupportedException {
            AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
            result.keySet = null;
            result.values = null;
            return result;
        }
  • 相关阅读:
    Linux Shell编程 sort、wc命令
    Linux Shell编程 sed命令
    Linux Shell编程 awk命令
    Linux Shell编程 cut、print命令
    Linux Shell基础 环境变量配置文件
    Linux Shell基础 read命令
    Linux Shell基础 位置参数变量、预定义变量
    MS DOS 命令大全
    sublime 快捷键
    滚动到页面底部继续加载页面其他内容
  • 原文地址:https://www.cnblogs.com/alimayun/p/10720434.html
Copyright © 2011-2022 走看看