zoukankan      html  css  js  c++  java
  • Map、AbstractMap、SortedMap、NavigableMap介绍(JDK1.8)

    简介

    Map接口与常见实现类的UML图:

    • Map实现的类存储对象是键值对

    • AbstractMap抽象类实现了Map接口部分方法,那么其他Map实现类可以通过继承AbstractMap来减少代码编写。

    • 实现了SortedMap接口的Map实现类具有排序键值对的功能。

    • NavigableMap接口继承自SortedMap接口,其具有获取大于|等于某对象的键值对、小于|等于某对象的键值对。

    • Dictionary抽象类存储键值对,与Map类似,但现在该类已过时。

    • HashMap继承AbstractMap类,能存储键值对,但不能保证插入次序。

    • HashTable实现Map、继承Dictionary,即也能存储键值对,但不保证次序。它是一个线程安全的类。

    • LinkedHashMap实现Map接口,继承HashMap,能存储键值对,也保证次序。

    • TreeMap继承AbstractMap类,也实现了NavigableMap接口,即内部是是有序的键值对。


    Map

    • Map是一个操作键值对映射的接口,一个键只能有一个,一个键对应一个值。

    • Map接口提供三种视图,分别是:键集、值集、键值集。

    • Map有些实现类能保证取出键值对与插入键值对次序一致,如LinkedHashMap;有些实现类能通过排序键值对, 如TreeMap。

    常用API
    Modifier and Type Method
    void clear()
    default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
    default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
    boolean containsKey(Object key)
    boolean containsValue(Object value)
    Set<Map.Entry<K,V>> entrySet()
    boolean equals(Object o)
    default void forEach(BiConsumer<? super K,? super V> action)
    V get(Object key)
    default V getOrDefault(Object key, V defaultValue)
    int hashCode()
    boolean isEmpty()
    Set<K> keySet()
    default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
    V put(K key, V value)
    void putAll(Map<? extends K,? extends V> m)
    default V putIfAbsent(K key, V value)
    V remove(Object key)
    default boolean remove(Object key, Object value)
    default V replace(K key, V value)
    default boolean replace(K key, V oldValue, V newValue)
    default void replaceAll(BiFunction<? super K,? super V,? extends V> function)
    int size()
    Collection<V> values()

    keySet()返回键集,values()返回值集,entrySet()返回键值集


    Map.Entry

    Entry是Map内部接口,其功能是对键值对进行操作。

    API

    Modifier and Type Method and Description
    static <K extends Comparable<? super K>,V>Comparator<Map.Entry<K,V>> comparingByKey()返回一个比较 ,按键自然顺序比较Map.Entry
    static <K,V> Comparator<Map.Entry<K,V>> comparingByKey(Comparator<? super K> cmp)返回一个比较器,比较Map.Entry按键使用给定的Comparator
    static <K,V extends Comparable<? super V>>Comparator<Map.Entry<K,V>> comparingByValue()返回一个比较器,比较Map.Entry的自然顺序值。
    static <K,V> Comparator<Map.Entry<K,V>> comparingByValue(Comparator<? super V> cmp)返回一个比较 ,使用给定的Comparator比较Map.Entry的值。
    boolean equals(Object o)将指定的对象与此条目进行比较以获得相等性。
    K getKey()返回与此条目相对应的键。
    V getValue()返回与此条目相对应的值。
    int hashCode()返回此映射条目的哈希码值。
    V setValue(V value)用指定的值替换与该条目相对应的值(可选操作)。

    AbstractMap

    属性
        transient Set<K>        keySet;键集视图
        transient Collection<V> values;值集视图
    
    源码分析
    		//唯一一个构造方法
    		protected AbstractMap() {}
    	
    		//返回键值集元素个数
        public int size() {
            return entrySet().size();
        }
    		
    		//判断该容器是否为空
        public boolean isEmpty() {
            return size() == 0;
        }
    
    		//查询该容器是否存在值为value
        public boolean containsValue(Object value) {
          //获取键值集的迭代器
            Iterator<Entry<K,V>> i = entrySet().iterator();
          //指定值为null的情况
            if (value==null) {
              	//通过迭代器遍历该容器
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getValue()==null)
                        return true;
                }
            } else {//指定值不为null情况
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (value.equals(e.getValue()))
                        return true;
                }
            }
            return false;
        }
    		
    		//查询该容器是否存在键为key
        public boolean containsKey(Object key) {
          	//获取键集视图的迭代器
            Iterator<Map.Entry<K,V>> i = entrySet().iterator();
          	//指定值为null的情况
            if (key==null) {
              //通过迭代器遍历该容器
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (e.getKey()==null)
                        return true;
                }
            } else {
              //指定值不为null的情况
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    if (key.equals(e.getKey()))
                        return true;
                }
            }
            return false;
        }
    
    		//通过键获取值,若查找不到返回null。
        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;
        }
    		
    		//通过键移除指定的键值对
        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();
                    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;
                }
            }
    
          	//oldValue为旧值
            V oldValue = null;
            if (correctEntry !=null) {
                oldValue = correctEntry.getValue();
              	//调用迭代器移除方法
                i.remove();
            }
            return oldValue;
        }
    
    		//添加其他容器数据
        public void putAll(Map<? extends K, ? extends V> m) {
          	//遍历容器内数据并一一添加
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
                put(e.getKey(), e.getValue());
        }
    
    		//对容器内所有映射
        public void clear() {
          	//先获取键值集再调用删除方法。
            entrySet().clear();
        }
    		
    		//获取键集视图
        public Set<K> keySet() {
            Set<K> ks = keySet;
            if (ks == null) {
              //如果成员变量 keySet 为 null,创建个空的 AbstractSet,并完成Iterator<K>()、size()、isEmpty()、clear()、contains(Object k)方法。
                ks = new AbstractSet<K>() {
                    public Iterator<K> iterator() {
                        return new Iterator<K>() {
                            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;
        }
    
    		//获取值集视图
        public Collection<V> values() {
            Collection<V> vals = values;
          //如果成员变量 vals 为 null,创建个空的 AbstractSet,并完成Iterator<K>()、size()、isEmpty()、clear()、contains(Object k)方法。
            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;
        }
    
    		//获取键值集方法未定义
        public abstract Set<Entry<K,V>> entrySet();
    
    		//判断对象o是否等于当前容器
        public boolean equals(Object o) {
          	//判断地址相等
            if (o == this)
                return true;
    				//判断是否为同一类型
            if (!(o instanceof Map))
                return false;
          	//强转为 Map
            Map<?,?> m = (Map<?,?>) o;
          	//判断大小是否相等
            if (m.size() != size())
                return false;
    			
            try {
              //下面就是使用容器的迭代器遍历元素,在判断对象o的map 是否包含指定键值对
                Iterator<Entry<K,V>> i = entrySet().iterator();
                while (i.hasNext()) {
                    Entry<K,V> e = i.next();
                    K key = e.getKey();
                    V value = e.getValue();
                    if (value == null) {
                        if (!(m.get(key)==null && m.containsKey(key)))
                            return false;
                    } else {
                        if (!value.equals(m.get(key)))
                            return false;
                    }
                }
            } catch (ClassCastException unused) {
                return false;
            } catch (NullPointerException unused) {
                return false;
            }
    
            return true;
        }
    		
    		
    //整个 map 的 hashCode()
        public int hashCode() {
            int h = 0;
            Iterator<Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext())
              	//是所有 Entry 哈希值的和
                h += i.next().hashCode();
            return h;
        }
    
       	//返回此 AbstractMap实例的浅拷贝:键和值本身不被克隆。
        protected Object clone() throws CloneNotSupportedException {
            AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
            result.keySet = null;
            result.values = null;
            return result;
        }
    
    		//判读o1,02是否相等
        private static boolean eq(Object o1, Object o2) {
            return o1 == null ? o2 == null : o1.equals(o2);
        }
    		
    
    AbstractMap.SimpleEntry类:

    表示可变的键值对

     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 int hashCode() {
                return (key   == null ? 0 :   key.hashCode()) ^
                       (value == null ? 0 : value.hashCode());
            }
    
            public String toString() {
                return key + "=" + value;
            }
    
        }
    
    AbstractMap.SimpleImmutableEntry类:

    表示一个不可变的键值对

    public static class SimpleImmutableEntry<K,V>
            implements Entry<K,V>, java.io.Serializable
        {
            private static final long serialVersionUID = 7138329143949025153L;
    
            private final K key;
            private final V value;
    
            public SimpleImmutableEntry(K key, V value) {
                this.key   = key;
                this.value = value;
            }
    
            public SimpleImmutableEntry(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) {
                throw new UnsupportedOperationException();
            }
    				//判断与另外一个键值对是否相等
            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;
            }
        }
    

    SortedMap接口

    API

    Modifier and Type Method and Description
    Comparator<? super K> comparator()
    Set<Map.Entry<K,V>> entrySet()
    K firstKey()
    SortedMap<K,V> headMap(K toKey)
    Set<K> keySet()
    K lastKey()
    SortedMap<K,V> subMap(K fromKey, K toKey)
    SortedMap<K,V> tailMap(K fromKey)
    Collection<V> values()
    源码
    public interface SortedMap<K,V> extends Map<K,V> {
        //返回与此有序映射关联的比较器,如果使用键的自然顺序,则返回 null
        Comparator<? super K> comparator();
    
      	//返回此有序映射的部分视图,其键值从 fromKey(包括)到 toKey(不包括)。
        SortedMap<K,V> subMap(K fromKey, K toKey);
    
      	//返回此有序映射的部分元素,其元素的键值应该小于 toKey。
        SortedMap<K,V> headMap(K toKey);
    
      	//返回有序映射的部分视图,其键大于或等于 fromKey。
        SortedMap<K,V> tailMap(K fromKey);
      
    		//返回有序映射中当前第一个(最小的)键。
        K firstKey();
    
      	//返回有序映射中当前最后一个(最大的)键。
        K lastKey();
    
      	//键集视图
        Set<K> keySet();
    
      	//值集视图
        Collection<V> values();
    
      	//键值集视图
        Set<Map.Entry<K, V>> entrySet();
    }
    
    

    简介

    NavigableMap是SortedMap的子接口,具有SortedMap更多功能。

    ​ 方法 lowerEntry、floorEntry、ceilingEntry 和 higherEntry 分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry 对象,如果不存在这样的键,则返回 null。

    ​ 类似地,方法 lowerKey、floorKey、ceilingKey 和 higherKey 只返回关联的键。

    ​ firstEntry、pollFirstEntry、lastEntry 和 pollLastEntry 方法,它们返回和/或移除最小和最大的映射关系(如果存在),否则返回 null。所有这些方法是为查找条目而不是遍历条目而设计的。

    API
    Modifier and Type Method
    Map.Entry<K,V> ceilingEntry(K key)
    K ceilingKey(K key)
    NavigableSet<K> descendingKeySet()
    NavigableMap<K,V> descendingMap()
    Map.Entry<K,V> firstEntry()
    Map.Entry<K,V> floorEntry(K key)
    K floorKey(K key)
    SortedMap<K,V> headMap(K toKey)
    NavigableMap<K,V> headMap(K toKey, boolean inclusive)
    Map.Entry<K,V> higherEntry(K key)
    K higherKey(K key)
    Map.Entry<K,V> lastEntry()
    Map.Entry<K,V> lowerEntry(K key)
    K lowerKey(K key)
    NavigableSet<K> navigableKeySet()
    Map.Entry<K,V> pollFirstEntry()
    Map.Entry<K,V> pollLastEntry()
    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
    SortedMap<K,V> subMap(K fromKey, K toKey)
    SortedMap<K,V> tailMap(K fromKey)
    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
  • 相关阅读:
    Cannot load php5apache2_4.dll into server
    PHP合并数组
    为什么 echo 3 . print(2) . print(4) . 5 . 'c'的结果是45c2131
    PHP数据类型
    PHP变量
    SSH Key
    VMware Tools安装教程
    nginx: [emerg] getpwnam("nginx") failed
    JS 生成随机数
    JS 操作 cookie
  • 原文地址:https://www.cnblogs.com/zitai/p/13206765.html
Copyright © 2011-2022 走看看