一、Map接口
1、结构
public interface Map<K, V> {
可以看到其是一个泛型接口,K -对应的key类型,V - 对应的value值类型。
2、内部接口Entry
这个接口是定义在Map接口的内部的。其表示的是以哪种结构存储key-value这种数据元素,例如这里的setKey方法、setValue方法。Map接口的不同子类可以决定key-value 映射元素不同的实现方式。
3、接口方法定义
1)、size()
int size();
表示此Map key-value 元素映射的个数。
2)、isEmpty()
boolean isEmpty();
此Map是否为空判断,没有 key-value 映射元素。
3)、containsKey(Object key);
boolean containsKey(Object key);
是否有这个key对应的映射元素。
4)、containsValue(Object value)
boolean containsValue(Object value);
是否包含有这个值的 映射元素。
5)、get(Object key)
V get(Object key);
根据这个key获取对应的映射元素对应的值。
6)、put(K key, V value)
V put(K key, V value);
将 此key-value构成的元素元素放到Map中。如果已经有这个key对应的映射元素了,则将原来元素的value换成这个新value。
7)、remove(Object key)
V remove(Object key);
移除此key对应的映射元素,同时将其的值返回。
8)、clear()
void clear();
清空此Map。
9)、keySet()
Set<K> keySet();
将此Map的key-value元素元素的所有key以Set集合的方式返回。
10)、values()
Collection<V> values();
与上面类似,将所有的value以Collection 的形式返回,只所以这两个方法就是Key是唯一的,而Value是可以相同的。
11)、entrySet()
Set<Map.Entry<K, V>> entrySet();
将Map的key-value元素元素以Set集合的方式返回。
12)、getOrDefault(Object key, V defaultValue)
default V getOrDefault(Object key, V defaultValue) {
V v;
return (((v = get(key)) != null) || containsKey(key))
? v
: defaultValue;
}
这个default在接口中实现方法是jdk8的特性,可以看到这个方法是如果能通过key获取到对应的value就将value返回,如果不能获取到对应元素就返回defaultValue这个传入的默认值(之所以用 “||” 连接get()方法与containsKey()方法是因为可以放value为null的映射元素)。
13)、putIfAbsent(K key, V value)
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
如果不存在这个key对应的元素就调用put放到放入这个key-value元素。这样就不会将原来的value覆盖了,直接调用put方法是会将原来的value覆盖的。
14)、remove(Object key, Object value)
default boolean remove(Object key, Object value) {
Object curValue = get(key);
if (!Objects.equals(curValue, value) ||
(curValue == null && !containsKey(key))) {
return false;
}
remove(key);
return true;
}
移除这个key-value对应的元素(要注意是key&value都要对应相等)。
15)、replace(K key, V oldValue, V newValue)
default boolean replace(K key, V oldValue, V newValue) {
Object curValue = get(key);
if (!Objects.equals(curValue, oldValue) ||
(curValue == null && !containsKey(key))) {
return false;
}
put(key, newValue);
return true;
}
类似Unsafe类的CAS操作,用新的value去替换key原来的value,不过这里我们可以看到其应该是一种不是线程安全的CAS操作,因为其的get()方法与put()方法并不是原子操作。
14)、replace(K key, V value)
default V replace(K key, V value) {
V curValue;
if (((curValue = get(key)) != null) || containsKey(key)) {
curValue = put(key, value);
}
return curValue;
}
替换原来的value,如果存在此key对应的元素。
二、AbstractMap
AbstractMap是Map接口的基类抽象实现。
1、结构&构造方法
public abstract class AbstractMap<K,V> implements Map<K,V> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractMap() {
}
实现Map接口的抽象方法。
2、对Entry接口的实现
public static class SimpleEntry<K,V>
implements Entry<K,V>, java.io.Serializable
{
private final K key;
private V value;
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
可以看到其就是简单定义了两个成员变量key&value用来存需要存储的key-value 对应的 Entry元素。
3、方法
1)、entrySet()
public abstract Set<Entry<K,V>> entrySet();
这个方法就是将当前Map的key-value元素以Set集合的方式返回,同时可以看到其实abstract,需要其的子类返回。
2)、size()
public int size() {
return entrySet().size();
}
这个其实就是判断set的集合的元素个数,也可以说是有多少给Entry元素。
3)、isEmpty()
public boolean isEmpty() {
return size() == 0;
}
看size是否为0。
4)、containsValue(Object 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;
}
判断是否有这个value对应的Entry元素。这里是通过Iterator去遍历Map中的Entry元素,这里是有两个分支,一个是如果value本身就是null的话,则是判断Entry的value是否为null由此来返回true,如果不是则是调用对应Value的equals方法判断。
5)、containsKey(Object 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也为null的情况的。
6)、get(Object 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;
}
迭代器遍历,再返回对应的value。
7)、put(K key, V value)
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
需要其的子类去支持实现,其返回UnsupportedOperationException异常。
8)、remove(Object 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;
}
获取key对应Entry元素的value。通过Iterator迭代器遍历,再通过key去判断获取对应的Entry,然后将该Entry的value返回同时再通过Iterator的remove方法删除此Entry。
9)、clear()
public void clear() {
entrySet().clear();
}
清空元素,直接调用的Set的clear方法。
10)、keySet&values变量
transient Set<K> keySet;
transient Collection<V> values;
这两个变量就是用来放key以及values的。
11)、keySet()
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
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;
}
这个就是获取key所对应的Set集合,可以看到其的初始化是直接通过AbstractSet去创建实现了一个匿名内部类。不过可以看到其内部迭代器的实现还是使用的entrySet()这个返回的集合对应的迭代器实现。
12)、values()
public Collection<V> values() {
Collection<V> vals = values;
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;
}
整体与前一个方法相似,只是这里是对AbstractCollection抽象类的实现。
13)、equals(Object o)
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
for (Entry<K, V> e : entrySet()) {
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;
}
这里AbstractMap类的equals方法的实现是有四层的。首先是通过this 相等判断(内存地址判断),再看入参是否为Map不为Map肯定是false,然后是size,之后再是遍历Entry判断。需要注意第四层判断,如果两者遍历匹配Entry的value如果为null,则是判断两者的key,不然是直接value判断。
14)、hashCode()
public int hashCode() {
int h = 0;
for (Entry<K, V> entry : entrySet())
h += entry.hashCode();
return h;
}
其的hashCode是所有的Entry对应的hashCode之和。