2019年06月19日(星期三)  农历:己亥年五月十七
  • 首页
  • JAVA
  • Map框架相关抽象类接口详解

作者:三年。分类: JAVA

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

一:Map总体框架图

\

简单说明:

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

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

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

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

二:Map

1、接口简介:

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

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

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

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

2、源码分析:

package com.chy.collection.core;

public interface Map {

// 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 m);

/** 删除当前Map中所有映射*/

void clear();

// Views

/** 获取由Map中所有key组成的Set*/

Set keySet();

/** 获取由Map中所有value组曾的Collection*/

Collection values();

/** 获取由Map中所有映射组成的实体类Map.Entry组成的Set*/

Set> entrySet();

/** 组成Map的键值对、仅在Iterator时使用*/

interface Entry {

/** 获取当前映射的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

1、抽象类简介:

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

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

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

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

2、源码分析:

package com.chy.collection.core;

import java.util.Iterator;

import java.util.Map.Entry;

public abstract class AbstractMap implements Map {

/** 默认的构造方法、供子类调用*/

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> i = entrySet().iterator();

if (value==null) {

while (i.hasNext()) {

Entry e = i.next();

if (e.getValue()==null)

return true;

}

} else {

while (i.hasNext()) {

Entry e = i.next();

if (value.equals(e.getValue()))

return true;

}

}

return false;

}

/** 判断当前Map中是否有键为key的映射*/

public boolean containsKey(Object key) {

Iterator> i = entrySet().iterator();

if (key==null) {

while (i.hasNext()) {

Entry e = i.next();

if (e.getKey()==null)

return true;

}

} else {

while (i.hasNext()) {

Entry e = i.next();

if (key.equals(e.getKey()))

return true;

}

}

return false;

}

/** 获取键为key的值*/

public V get(Object key) {

Iterator> i = entrySet().iterator();

if (key==null) {

while (i.hasNext()) {

Entry e = i.next();

if (e.getKey()==null)

return e.getValue();

}

} else {

while (i.hasNext()) {

Entry 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> i = entrySet().iterator();

Entry correctEntry = null;

if (key==null) {

while (correctEntry==null && i.hasNext()) {

Entry e = i.next();

if (e.getKey()==null)

correctEntry = e;

}

} else {

while (correctEntry==null && i.hasNext()) {

Entry 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 m) {

for (Map.Entry e : m.entrySet())

put(e.getKey(), e.getValue());

}

/** 清空当前Map*/

public void clear() {

entrySet().clear();

}

// Views

transient volatile Set keySet = null;

transient volatile Collection values = null;

/** 获取有当前Map中所有key组成的Set*/

public Set keySet() {

if (keySet == null) {

//通过匿名类的方式获取keySet实体类

keySet = new AbstractSet() {

//实现获取Iterator的方法、并实现Iterator内部方法

public Iterator iterator() {

return new Iterator() {

private Iterator> 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 values() {

if (values == null) {

//通过匿名类的方式获取Collection实体类

values = new AbstractCollection() {

//实现获取Iterator的方法、并实现Iterator内部方法

public Iterator iterator() {

return new Iterator() {

private Iterator> 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> entrySet();

// Comparison and hashing

public boolean equals(Object o) {

//如果是他本身、返回true

if (o == this)

return true;

//如果传入的不是Map、返回false

if (!(o instanceof Map))

return false;

Map m = (Map) o;

//优化操作、如果传入的Map的size与当前被比较的Map的size不同、那么就可确定这两个Map不相等

if (m.size() != size())

return false;

//比较两个Map中的所有value是否相等、相等则返回true、不相等则返回false

try {

Iterator> i = entrySet().iterator();

while (i.hasNext()) {

Entry 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> i = entrySet().iterator();

while (i.hasNext())

h += i.next().hashCode();

return h;

}

/** 返回此映射的字符串表示形式。*/

public String toString() {

Iterator> i = entrySet().iterator();

if (! i.hasNext())

return "{}";

StringBuilder sb = new StringBuilder();

sb.append('{');

for (;;) {

Entry 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 result = (AbstractMap)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 implements Entry, 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 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 implements Entry, 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 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

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 extends Map {

/** 返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回 null。*/

Comparator comparator();

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

SortedMap subMap(K fromKey, K toKey);

/** 返回此映射的部分视图,其键值严格小于 toKey。*/

SortedMap headMap(K toKey);

/** 返回此映射的部分视图,其键大于等于 fromKey。*/

SortedMap tailMap(K fromKey);

/** 返回此映射中当前第一个(最低)键。*/

K firstKey();

/** 返回此映射中当前第一个(最低)键。*/

K lastKey();

/** 返回在此映射中所包含键的 Set 视图。*/

Set keySet();

/** 返回在此映射中所包含值的 Collection 视图。*/

Collection values();

/** 返回在此映射中包含的映射关系的 Set 视图。*/

Set> entrySet();

}

五:NavigableMap

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 extends SortedMap {

/** 返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。*/

Map.Entry lowerEntry(K key);

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

K lowerKey(K key);

/** 返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/

Map.Entry floorEntry(K key);

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

K floorKey(K key);

/** 返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。*/

Map.Entry ceilingEntry(K key);

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

K ceilingKey(K key);

/** 返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。*/

Map.Entry higherEntry(K key);

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

K higherKey(K key);

/** 返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/

Map.Entry firstEntry();

/** 返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。*/

Map.Entry lastEntry();

/** 移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。*/

Map.Entry pollFirstEntry();

/** 移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。*/

Map.Entry pollLastEntry();

/** 返回此映射中所包含映射关系的逆序视图。*/

NavigableMap descendingMap();

/** 返回此映射中所包含键的 NavigableSet 视图。*/

NavigableSet navigableKeySet();

/** 返回此映射中所包含键的逆序 NavigableSet 视图。*/

NavigableSet descendingKeySet();

/** 返回此映射的部分视图,其键的范围从 fromKey 到 toKey。*/

NavigableMap subMap(K fromKey, boolean fromInclusive,

K toKey, boolean toInclusive);

/** 返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。*/

NavigableMap headMap(K toKey, boolean inclusive);

/** 返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。*/

NavigableMap tailMap(K fromKey, boolean inclusive);

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

SortedMap subMap(K fromKey, K toKey);

/** 返回此映射的部分视图,其键值严格小于 toKey。*/

SortedMap headMap(K toKey);

/** 返回此映射的部分视图,其键大于等于 fromKey。*/

SortedMap tailMap(K fromKey);

}

温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,谢谢合作!

已有 0/1304 人参与

发表评论:



手Q扫描加入Java初学者群