java_集合体系之Map框架相关抽象类接口详解、源码
摘要:Set的实现是基于Map的、所以先搞懂Map、才能去理解Set、否则的话、直接去弄Set会觉得云里雾里、最后发现是浪费时间。这一节介绍关于Map的相关接口、抽象类的功能。
一:Map总体框架图
简单说明:
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)方法 lowerEntry
、floorEntry
、ceilingEntry
和higherEntry
分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry
对象。
c)方法 lowerKey
、floorKey
、ceilingKey
和higherKey
只返回关联的键。
d)可以按照键的升序或降序访问和遍历 NavigableMap
e)subMap
、headMap
和tailMap
方法与名称相似的 SortedMap
方法的不同之处在于:可以接受用于描述是否包括(或不包括)下边界和上边界的附加参数
f)firstEntry
、pollFirstEntry
、lastEntry
和pollLastEntry
方法,它们返回和/或移除最小和最大的映射关系(如果存在),否则返回 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);
- }