JDK11
AbstractMap
public abstract class AbstractMap<K,V> implements Map<K,V> {
Map的抽象类实现,那有哪些Map继承了这个抽象类呢?
- EnumMap
- HashMap
- IdentityHashMap
- LinkedHashMap
- WeakHashMap
- TreeMap
未来一周的计划就是把这些Map的底层实现彻底搞懂
transient Set<K> keySet; // key的集合
transient Collection<V> values; // value的集合
// 常用的entrySet实际上是一个Set,基本数据类型是Entry<K,V>
public abstract Set<Entry<K, V>> entrySet();
那这个Entry又指的是什么呢?
这个键值对实体的实现定义在Map.java
interface Entry<K, V> {
- hashCode
Map的hascode等于所有entry的hashCode之和
public int hashCode() {
int h = 0;
for(Entry<K, V> entry : entrySet()) {
h += entry.hashCode();
}
return h;
}
- equals
1.如果所比较对象等于自身引用返回true
2.如果所比较对象不是Map类型返回false
3.把所比较对象类型转换为Map
4.互相比较两个map的entry,如果value为null,判断条件是map存在对应的key并且比较对象的key对应value也为null
如果value不为null,判断条件是用equals判断是否相同。
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;
}
- toString
没啥好说的,就用StringBuilder
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(',').append(' ');
}
}
- clone
浅拷贝,只复制了map应用本身,其key和value都是没有复制的,都是指向原来的key和value
protected Object clone() throws CloneNotSupportedException {
AbstractMap<?, ?> result = (AbstractMap<?, ?>) super.clone();
result.keySet = null;
result.values = null;
return result;
}
其他的put,get,remove方法都很常规我就不说了
另外要提一下定义了两个简单的键值对实现了Entry接口
-
SimpleEntry
-
SimpleImmutableEntry
两个区别是后者的value用了final修饰,setValue方法并没有实现,抛出Exception
Entry的hashcode方法:
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
}
key和value取异或
AbstractSet
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
和AbstractMap不同的是,这个抽象类还继承了AbstractCollection这个抽象父类,
public boolean equals(Object o) {
if(o == this) {
return true;
}
if(!(o instanceof Set)) {
return false;
}
Collection<?> c = (Collection<?>) o;
if(c.size() != size()) {
return false;
}
try {
// 只要两个set包含的元素都相同就可以说明equals
return containsAll(c);
} catch(ClassCastException | NullPointerException unused) {
return false;
}
}
- hashcode
public int hashCode() {
int h = 0;
for(E obj : this) {
if(obj != null) {
h += obj.hashCode();
}
}
return h;
}
Set中所有元素hashcode累加和
- removeAll
没啥好说的。。。
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
if(size()>c.size()) {
for(Object e : c) {
modified |= remove(e);
}
} else {
for(Iterator<?> i = iterator(); i.hasNext(); ) {
if(c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}