java_集合体系之Map框架相关抽象类接口详解、源码——08

java_集合体系之Map框架相关抽象类接口详解、源码——08


        摘要:Set的实现是基于Map的、所以先搞懂Map、才能去理解Set、否则的话、直接去弄Set会觉得云里雾里、最后发现是浪费时间。这一节介绍关于Map的相关接口、抽象类的功能。


一:Map总体框架图

 java_集合体系之Map框架相关抽象类接口详解、源码——08_第1张图片

简单说明:

        1、上图中虚线且无依赖字样、说明是直接实现的接口

        2、虚线但是有依赖字样、说明此类依赖与接口、但不是直接实现接口

        3、实线是继承关系、类继承类、接口继承接口

        下面的介绍虽然这些都是关于抽象类、接口的定义、但是还是觉得从源码的方向介绍更能直观的说明问题、也更能加深对体系的理解、当然API同样不再给出、会在介绍其具体子类的时候将接口中的API和子类自己新增的API分离开来罗列。


二:Map<K, V>


        1、接口简介:

                a)以键值对的形式存储数据、每个键唯一对应一个值、键不允许重复、至于键是否允许为null、视子类而定。

                b)其中存放元素是否有序、视子类而定、如HashMap无序、Hashtable有序、排序规则可选按自然排序或者指定排序方式。

                c)允许以三种形式获取、迭代Map中的元素、获取键集、获取值集、获取键值实体。

                d)子类必须提供两个构造方法、一个是空构造方法、一个是含有指定传入的Map结构中的所有键值对的构造方法(此构造方法是将指定传入的Map智中的键值对全部复制为自己的键值对)。


        2、源码分析:


package com.chy.collection.core;

public interface Map<K,V> {
    // Query Operations

    /** 返回所有的映射的个数*/
    int size();

    /** 是否含有映射*/
    boolean isEmpty();

    /** 是否包含值为key的key*/
    boolean containsKey(Object key);

    /** 是否包含值为value的value*/
    boolean containsValue(Object value);

    /** 根据指定的key获取value*/
    V get(Object key);

    // Modification Operations

    /** 将一个键值对放入到Map中、返回以前与key关联的值*/
    V put(K key, V value);

    /** 根据传入的key删除一个键值对、返回被删除的key映射的value*/
    V remove(Object key);


    // Bulk Operations

    /** 将指定的Map中的所有的映射放入到当前Map中*/
    void putAll(Map<? extends K, ? extends V> m);

    /** 删除当前Map中所有映射*/
    void clear();


    // Views

    /** 获取由Map中所有key组成的Set*/
    Set<K> keySet();

    /** 获取由Map中所有value组曾的Collection*/
    Collection<V> values();

    /** 获取由Map中所有映射组成的实体类Map.Entry<K, V>组成的Set*/
    Set<Map.Entry<K, V>> entrySet();

    /** 组成Map的键值对、仅在Iterator时使用*/
    interface Entry<K,V> {
    	/** 获取当前映射的key*/
    	K getKey();

    	/** 获取当前映射的value*/
    	V getValue();

    	/** 设置当前映射的value*/
		V setValue(V value);

		/** 判断当前Entry是否与传入的Object相等*/
		boolean equals(Object o);

		/**获取当前Entry的哈希值*/
		int hashCode();
    }

    // Comparison and hashing

    /** 如果 m1.entrySet().equals(m2.entrySet()),则两个映射 m1 和 m2 表示相同的映射关系。*/
    boolean equals(Object o);

    /** 返回此映射的哈希值*/
    int hashCode();
}


        简单说明:Map的源码中的方法可以分成:查询、修改(包括添加、删除Map中的映射)、获取视图和一个仅在Iterator的时候使用的内部接口、接口中定义了操作迭代出的每个映射的方法——获取key、获取value、修改映射的value。源码==================

 

三:AbstractMap<K, V>


        1、抽象类简介:

        a)AbstractMap实现了Map接口、提供一些方法的实现、要求所有需要实现Map接口的实现类应该从AbstractMap中继承、可以大大简化编程的代码量。

        b)AbstractMap中的方法的简单实现都是围绕第一个获取视图的方法Set<Map.Entry<K, V>> entrySet();得到entrySet、进而获取entrySet的Iterator来操作的、

        c)获取视图的剩下两个方法方法是通过两个匿名类new AbstractSet<K>()、newAbstractCollection<V>来实现的。    

        d)还有两个内部类是维护键值对的。

        2、源码分析:


package com.chy.collection.core;
import java.util.Iterator;
import java.util.Map.Entry;

public abstract class AbstractMap<K,V> implements Map<K,V> {
    /** 默认的构造方法、供子类调用*/
    protected AbstractMap() {}

    // Query Operations

    /** 返回当前Map映射个数*/
    public int size() {
    	return entrySet().size();
    }

    /** 当前映射是否为空*/
    public boolean isEmpty() {
    	return size() == 0;
    }

    /** 判断当前Map中是否有值为value的映射*/
    public boolean containsValue(Object value) {
		Iterator<Entry<K,V>> i = entrySet().iterator();
		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;
    }

    /** 判断当前Map中是否有键为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;
    }

    /** 获取键为key的值*/
    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;
    }


    // Modification Operations

    /** 将一个映射放入到Map中、要求子类要有自己的实现*/
    public V put(K key, V value) {
    	throw new UnsupportedOperationException();
    }

    /** 删除键为key的映射*/
    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;
		    }
		}
	
		V oldValue = null;
		if (correctEntry !=null) {
		    oldValue = correctEntry.getValue();
		    i.remove();
		}
		return oldValue;
    }


    // Bulk Operations

    /** 将指定Map中所有键值对都放入到当前Map中*/
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }

    /** 清空当前Map*/
    public void clear() {
    	entrySet().clear();
    }


    // Views

    transient volatile Set<K>        keySet = null;
    transient volatile Collection<V> values = null;

    /** 获取有当前Map中所有key组成的Set*/
    public Set<K> keySet() {
		if (keySet == null) {
			//通过匿名类的方式获取keySet实体类
		    keySet = new AbstractSet<K>() {
		    	//实现获取Iterator的方法、并实现Iterator内部方法
				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 contains(Object k) {
				    return AbstractMap.this.containsKey(k);
				}
		    };
		}
		return keySet;
    }

    /** 获取当前Map所有value组成的集合*/
    public Collection<V> values() {
		if (values == null) {
			//通过匿名类的方式获取Collection实体类
		    values = new AbstractCollection<V>() {
		    	//实现获取Iterator的方法、并实现Iterator内部方法
				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 contains(Object v) {
				    return AbstractMap.this.containsValue(v);
				}
		    };
		}
		return values;
    }

    /** 获取由当前Map中所有映射组成的Set*/
    public abstract Set<Entry<K,V>> entrySet();


    // Comparison and hashing

    public boolean equals(Object o) {
    	//如果是他本身、返回true
		if (o == this)
		    return true;
		
		//如果传入的不是Map、返回false
		if (!(o instanceof Map))
		    return false;
		Map<K,V> m = (Map<K,V>) o;
		//优化操作、如果传入的Map的size与当前被比较的Map的size不同、那么就可确定这两个Map不相等
		if (m.size() != size())
		    return false;
		
		//比较两个Map中的所有value是否相等、相等则返回true、不相等则返回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();
                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;
    }

    /**  返回此映射的哈希码值。*/
    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(", ");
		}
    }

    /** 返回当前Map的克隆的值*/
    protected Object clone() throws CloneNotSupportedException {
        AbstractMap<K,V> result = (AbstractMap<K,V>)super.clone();
        result.keySet = null;
        result.values = null;
        return result;
    }

    /** 比较两个对象是否相等*/
    private static boolean eq(Object o1, Object o2) {
        return o1 == null ? o2 == null : o1.equals(o2);
    }

    // Implementation Note: SimpleEntry and SimpleImmutableEntry
    // are distinct unrelated classes, even though they share
    // some code. Since you can't add or subtract final-ness
    // of a field in a subclass, they can't share representations,
    // and the amount of duplicated code is too small to warrant
    // exposing a common abstract class.


    /** 维护键和值的 Entry、此类支持setValue*/
    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;
		}
    }

    /**维护不可变的键和值的 Entry、此类不支持 setValue 方法。一般用在多线程环境中*/
    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<K, V>


        1、接口简介:

        a)进一步提供关于键的总体排序的Map。该映射是根据其键的自然顺序进行排序的,或者根据通常在创建有序映射时提供的Comparator 进行排序

 

        b)插入所有有序映射的键都要实现Comparable接口、所有这些键都是可以比较的。

 

        c)内部方法都是围绕key的排序定义的、概括为: (1)获取大于、小于指定键的子Map、       (2)获取key所在指定范围的子集Map。获取第一个、最后一个键、    (3)获取三种视图的方法。(4)获取当前集合的排序比较器。

        2、源码分析:

      

package com.chy.collection.core;

import java.util.Comparator;


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 视图。*/
    Set<K> keySet();

    /**  返回在此映射中所包含值的 Collection 视图。*/
    Collection<V> values();

    /** 返回在此映射中包含的映射关系的 Set 视图。*/
    Set<Map.Entry<K, V>> entrySet();
}


五:NavigableMap<K, V>


        1、接口简介:

                a)是对SortedMap接口的扩展、

                b)方法 lowerEntryfloorEntryceilingEntryhigherEntry 分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry 对象。

                c)方法 lowerKeyfloorKeyceilingKeyhigherKey 只返回关联的键。

                d)可以按照键的升序或降序访问和遍历 NavigableMap

                e)subMapheadMaptailMap 方法与名称相似的 SortedMap 方法的不同之处在于:可以接受用于描述是否包括(或不包括)下边界和上边界的附加参数

                f)firstEntrypollFirstEntrylastEntrypollLastEntry 方法,它们返回和/或移除最小和最大的映射关系(如果存在),否则返回 null

        2、源码分析:


package com.chy.collection.core;

import java.util.NavigableSet;

public interface NavigableMap<K,V> extends SortedMap<K,V> {
	
    /** 返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。*/
    Map.Entry<K,V> lowerEntry(K key);

    /**  返回严格小于给定键的最大键;如果不存在这样的键,则返回 null。*/
    K lowerKey(K key);

    /**  返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/
    Map.Entry<K,V> floorEntry(K key);

    /** 返回小于等于给定键的最大键;如果不存在这样的键,则返回 null。*/
    K floorKey(K key);

    /**  返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。*/
    Map.Entry<K,V> ceilingEntry(K key);

    /** 返回大于等于给定键的最小键;如果不存在这样的键,则返回 null。*/
    K ceilingKey(K key);

    /** 返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。*/
    Map.Entry<K,V> higherEntry(K key);

    /**  返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。*/
    K higherKey(K key);

    /** 返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/
    Map.Entry<K,V> firstEntry();

    /** 返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。*/
    Map.Entry<K,V> lastEntry();

    /** 移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/
    Map.Entry<K,V> pollFirstEntry();

    /**  移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。*/
    Map.Entry<K,V> pollLastEntry();

    /** 返回此映射中所包含映射关系的逆序视图。*/
    NavigableMap<K,V> descendingMap();

    /**  返回此映射中所包含键的 NavigableSet 视图。*/
    NavigableSet<K> navigableKeySet();

    /** 返回此映射中所包含键的逆序 NavigableSet 视图。*/
    NavigableSet<K> descendingKeySet();

    /**  返回此映射的部分视图,其键的范围从 fromKey 到 toKey。*/
    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
                             K toKey,   boolean toInclusive);

    /** 返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。*/
    NavigableMap<K,V> headMap(K toKey, boolean inclusive);

    /**  返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。*/
    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);

    /** 返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。*/
    SortedMap<K,V> subMap(K fromKey, K toKey);

    /** 返回此映射的部分视图,其键值严格小于 toKey。*/
    SortedMap<K,V> headMap(K toKey);

    /** 返回此映射的部分视图,其键大于等于 fromKey。*/
    SortedMap<K,V> tailMap(K fromKey);
}


更多内容:java_集合体系之总体目录——00


你可能感兴趣的:(源码,java集合,Map框架图,AbstractMap,SortedMap)