摘要:Set的实现是基于Map的、所以先搞懂Map、才能去理解Set、否则的话、直接去弄Set会觉得云里雾里、最后发现是浪费时间。这一节介绍关于Map的相关接口、抽象类的功能。
简单说明:
1、上图中虚线且无依赖字样、说明是直接实现的接口
2、虚线但是有依赖字样、说明此类依赖与接口、但不是直接实现接口
3、实线是继承关系、类继承类、接口继承接口
下面的介绍虽然这些都是关于抽象类、接口的定义、但是还是觉得从源码的方向介绍更能直观的说明问题、也更能加深对体系的理解、当然API同样不再给出、会在介绍其具体子类的时候将接口中的API和子类自己新增的API分离开来罗列。
a)以键值对的形式存储数据、每个键唯一对应一个值、键不允许重复、至于键是否允许为null、视子类而定。
b)其中存放元素是否有序、视子类而定、如HashMap无序、Hashtable有序、排序规则可选按自然排序或者指定排序方式。
c)允许以三种形式获取、迭代Map中的元素、获取键集、获取值集、获取键值实体。
d)子类必须提供两个构造方法、一个是空构造方法、一个是含有指定传入的Map结构中的所有键值对的构造方法(此构造方法是将指定传入的Map智中的键值对全部复制为自己的键值对)。
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。源码==================
a)AbstractMap实现了Map接口、提供一些方法的实现、要求所有需要实现Map接口的实现类应该从AbstractMap中继承、可以大大简化编程的代码量。
b)AbstractMap中的方法的简单实现都是围绕第一个获取视图的方法Set<Map.Entry<K, V>> entrySet();得到entrySet、进而获取entrySet的Iterator来操作的、
c)获取视图的剩下两个方法方法是通过两个匿名类new AbstractSet<K>()、newAbstractCollection<V>来实现的。
d)还有两个内部类是维护键值对的。
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; } } }
a)进一步提供关于键的总体排序的Map。该映射是根据其键的自然顺序进行排序的,或者根据通常在创建有序映射时提供的Comparator 进行排序
b)插入所有有序映射的键都要实现Comparable接口、所有这些键都是可以比较的。
c)内部方法都是围绕key的排序定义的、概括为: (1)获取大于、小于指定键的子Map、 (2)获取key所在指定范围的子集Map。获取第一个、最后一个键、 (3)获取三种视图的方法。(4)获取当前集合的排序比较器。
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(); }
a)是对SortedMap接口的扩展、
b)方法 lowerEntry
、floorEntry
、ceilingEntry
和higherEntry
分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry
对象。
c)方法 lowerKey
、floorKey
、ceilingKey
和higherKey
只返回关联的键。
d)可以按照键的升序或降序访问和遍历 NavigableMap
e)subMap
、headMap
和tailMap
方法与名称相似的 SortedMap
方法的不同之处在于:可以接受用于描述是否包括(或不包括)下边界和上边界的附加参数
f)firstEntry
、pollFirstEntry
、lastEntry
和pollLastEntry
方法,它们返回和/或移除最小和最大的映射关系(如果存在),否则返回 null
。
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); }