类关系图
功能介绍
包路径:java.util
说明:AbstractMap直接实现了Map接口,是一个抽象类,而抽象类通常作为骨架使用,实现一些简单且通用的功能,而核心功能则由子类实现。
AbstractMap是大部分Map接口实现类的父类,典型常用的几个如HashMap、TreeMap、WeakHashMap等。
源码解析
/**
* This class provides a skeletal implementation of the <tt>Map</tt>
* interface, to minimize the effort required to implement this interface.
*
* 此类提供了一个Map接口的骨架实现,以尽可能减少其他类实现Map接口的工作量
*
* @param <K> the type of keys maintained by this map Map映射的key类型
* @param <V> the type of mapped values Map映射的value类型
*
* @author Josh Bloch
* @author Neal Gafter
* @see Map
* @see Collection
* @since 1.2
*/
public abstract class AbstractMap<K,V> implements Map<K,V> {
/**
* Sole constructor. (For invocation by subclass constructors, typically
* implicit.)
*/
protected AbstractMap() {
}
// Query Operations 检索操作实现
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns <tt>entrySet().size()</tt>.
*/
public int size() {
return entrySet().size(); // 直接返回Map内部维护的Entry实体个数,即映射个数
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns <tt>size() == 0</tt>.
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Map中是否存在目标value
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt> searching
* for an entry with the specified value. If such an entry is found,
* <tt>true</tt> is returned. If the iteration terminates without
* finding such an entry, <tt>false</tt> is returned. Note that this
* implementation requires linear time in the size of the map.
*/
public boolean containsValue(Object value) {
// Entry集合迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
if (value==null) {
// 遍历Entry集合并比较value
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getValue()==null)
return true;
}
} else {
// 遍历Entry集合并比较value
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (value.equals(e.getValue()))
return true;
}
}
return false;
}
/**
* Map中是否存在目标key对应映射
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt> searching
* for an entry with the specified key. If such an entry is found,
* <tt>true</tt> is returned. If the iteration terminates without
* finding such an entry, <tt>false</tt> is returned. Note that this
* implementation requires linear time in the size of the map; many
* implementations will override this method.
*/
public boolean containsKey(Object key) {
// Entry集合迭代器
Iterator<Map.Entry<K,V>> i = entrySet().iterator();
if (key==null) {
// 遍历Entry集合并比较key
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return true;
}
} else {
// 遍历Entry集合并比较key
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
return true;
}
}
return false;
}
/**
* 据传入的key获取当前映射中对应的value,如果存在对应映射关系,则返回对应值,否则返回null
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt> searching
* for an entry with the specified key. If such an entry is found,
* the entry's value is returned. If the iteration terminates without
* finding such an entry, <tt>null</tt> is returned. Note that this
* implementation requires linear time in the size of the map; many
* implementations will override this method.
*/
public V get(Object key) {
// Entry集合迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
if (key==null) {
// 遍历Entry集合并比较key
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
return e.getValue();
}
} else {
// 遍历Entry集合并比较key
while (i.hasNext()) {
Entry<K,V> e = i.next();
if (key.equals(e.getKey()))
return e.getValue();
}
}
// 默认返回null
return null;
}
// Modification Operations 变更操作
/**
* 向当前Map映射中存放键值对,由子类实现
*
* @implSpec
* This implementation always throws an
* <tt>UnsupportedOperationException</tt>.
*
*/
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
/**
* 从当前Map映射中移除以目标key为键的映射关系,并返回key对应的value,如果没有映射关系则返回null
*
* @implSpec
* This implementation iterates over <tt>entrySet()</tt> searching for an
* entry with the specified key. If such an entry is found, its value is
* obtained with its <tt>getValue</tt> operation, the entry is removed
* from the collection (and the backing map) with the iterator's
* <tt>remove</tt> operation, and the saved value is returned. If the
* iteration terminates without finding such an entry, <tt>null</tt> is
* returned. Note that this implementation requires linear time in the
* size of the map; many implementations will override this method.
*/
public V remove(Object key) {
// Entry集合迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
// 定义目标Entry,即目标映射对象
Entry<K,V> correctEntry = null;
// 如果key为null
if (key==null) {
// 遍历Entry集合,当前entry的key为null时,赋值给correctEntry
while (correctEntry==null && i.hasNext()) {
Entry<K,V> e = i.next();
if (e.getKey()==null)
correctEntry = e;
}
} else {
// 遍历Entry集合,当前entry的key与目标key相等时,赋值给correctEntry
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中
*
* @implSpec
* This implementation iterates over the specified map's
* <tt>entrySet()</tt> collection, and calls this map's <tt>put</tt>
* operation once for each entry returned by the iteration.
*/
public void putAll(Map<? extends K, ? extends V> m) {
// 遍历m中的Entry集合
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
// 拷贝映射
put(e.getKey(), e.getValue());
}
/**
* 清空当前Map所有映射
*
* @implSpec
* This implementation calls <tt>entrySet().clear()</tt>.
*
* <p>Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
* does not support the <tt>clear</tt> operation.
*
* @throws UnsupportedOperationException {@inheritDoc}
*/
public void clear() {
entrySet().clear(); // Set集合的Clear方法
}
// Views 视图
/**
* Each of these fields are initialized to contain an instance of the
* appropriate view the first time this view is requested. The views are
* stateless, so there's no reason to create more than one of each.
*
* transient关键字防止被序列化
*/
transient Set<K> keySet; // 存储所有key的set集合
transient Collection<V> values; // 存储所有value的集合
/**
* 返回key的set集合
*
* @implSpec
* This implementation returns a set that subclasses {@link AbstractSet}.
* The subclass's iterator method returns a "wrapper object" over this
* map's <tt>entrySet()</tt> iterator. The <tt>size</tt> method
* delegates to this map's <tt>size</tt> method and the
* <tt>contains</tt> method delegates to this map's
* <tt>containsKey</tt> method.
*/
public Set<K> keySet() {
Set<K> ks = keySet;
// 如果当前keySet为null
if (ks == null) {
// 构建一个AbstractSet,以Map的key类型为泛型参数,即key的set集合
ks = new AbstractSet<K>() {
// 定义AbstractSet的迭代器
public Iterator<K> iterator() {
return new Iterator<K>() {
// Entry的set集合迭代器
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();
}
};
}
// AbstractMap.this即ks
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;
}
// 返回keySet
return ks;
}
/**
* 获取value集合
*
* @implSpec
* This implementation returns a collection that subclasses {@link
* AbstractCollection}. The subclass's iterator method returns a
* "wrapper object" over this map's <tt>entrySet()</tt> iterator.
* The <tt>size</tt> method delegates to this map's <tt>size</tt>
* method and the <tt>contains</tt> method delegates to this map's
* <tt>containsValue</tt> method.
*
*/
public Collection<V> values() {
Collection<V> vals = values;
if (vals == null) {
// 构建匿名内部AbstractCollection,以Map的value类型为泛型参数,即value的列表
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;
}
// 返回该map中所有映射的Set视图。由子类实现
public abstract Set<Entry<K,V>> entrySet();
// Comparison and hashing
/**
* 比较两个Map,如果两个Map映射完全一样【ker和value完全一致】,返回true
*
* @param o object to be compared for equality with this map
* @return <tt>true</tt> if the specified object is equal to this map
*/
public boolean equals(Object o) {
// 如果就是本对象
if (o == this)
return true;
// 如果传入对象不是Map类型,直接返回false
if (!(o instanceof Map))
return false;
// 强转
Map<?,?> m = (Map<?,?>) o;
// 先比较记录数
if (m.size() != size())
return false;
try {
// Entry集合迭代器
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
// 比对当前Entry与传入Map对应key的映射是否一致
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;
}
/**
*
* @return the hash code value for this map
* @see Map.Entry#hashCode()
* @see Object#equals(Object)
* @see Set#equals(Object)
*/
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}
/**
*
* @return a string representation of this map
*/
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(' ');
}
}
/**
* Returns a shallow copy of this <tt>AbstractMap</tt> instance: the keys
* and values themselves are not cloned.
*
* @return a shallow copy of this map
*/
protected Object clone() throws CloneNotSupportedException {
AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
result.keySet = null;
result.values = null;
return result;
}
/**
* Utility method for SimpleEntry and SimpleImmutableEntry.
* Test for equality, checking for nulls.
*
* NB: Do not replace with Object.equals until JDK-8015417 is resolved.
*/
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.
/**
* Map中内部接口Entry的简单实现
*
* @since 1.6
*/
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;
/**
* Creates an entry representing a mapping from the specified
* key to the specified value.
*
* @param key the key represented by this entry
* @param value the value represented by this entry
*/
public SimpleEntry(K key, V value) {
this.key = key;
this.value = value;
}
/**
* Creates an entry representing the same mapping as the
* specified entry.
*
* @param entry the entry to copy
*/
public SimpleEntry(Entry<? extends K, ? extends V> entry) {
this.key = entry.getKey();
this.value = entry.getValue();
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
*/
public K getKey() {
return key;
}
/**
* Returns the value corresponding to this entry.
*
* @return the value corresponding to this entry
*/
public V getValue() {
return value;
}
/**
* Replaces the value corresponding to this entry with the specified
* value.
*
* @param value new value to be stored in this entry
* @return the old value corresponding to the entry
*/
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
/**
*
* @param o object to be compared for equality with this map entry
* @return {@code true} if the specified object is equal to this map
* entry
* @see #hashCode
*/
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());
}
/**
*
* @return the hash code value for this map entry
* @see #equals
*/
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
/**
* Returns a String representation of this map entry. This
* implementation returns the string representation of this
* entry's key followed by the equals character ("<tt>=</tt>")
* followed by the string representation of this entry's value.
*
* @return a String representation of this map entry
*/
public String toString() {
return key + "=" + value;
}
}
/**
* Entry接口的实现类,但entry对象是不可改变的,即key和value确定后,不能更改
*
* @since 1.6
*/
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;
/**
* Creates an entry representing a mapping from the specified
* key to the specified value.
*
* @param key the key represented by this entry
* @param value the value represented by this entry
*/
public SimpleImmutableEntry(K key, V value) {
this.key = key;
this.value = value;
}
/**
* Creates an entry representing the same mapping as the
* specified entry.
*
* @param entry the entry to copy
*/
public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
this.key = entry.getKey();
this.value = entry.getValue();
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
*/
public K getKey() {
return key;
}
/**
* Returns the value corresponding to this entry.
*
* @return the value corresponding to this entry
*/
public V getValue() {
return value;
}
/**
* value仅能通过初始创建即设置,不能进行修改,抛出异常
*/
public V setValue(V value) {
throw new UnsupportedOperationException();
}
/**
*
* @param o object to be compared for equality with this map entry
* @return {@code true} if the specified object is equal to this map
* entry
* @see #hashCode
*/
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());
}
/**
*
* @return the hash code value for this map entry
* @see #equals
*/
public int hashCode() {
return (key == null ? 0 : key.hashCode()) ^
(value == null ? 0 : value.hashCode());
}
/**
*
* @return a String representation of this map entry
*/
public String toString() {
return key + "=" + value;
}
}
}
总结
1、AbstractMap实现了Map接口,是一个抽象类,而抽象类通常作为骨架使用,实现一些简单且通用的功能,而核心功能则由子类实现。
2、AbstractMap是大部分Map接口实现类的父类,典型常用的几个如HashMap、TreeMap、WeakHashMap等
思考
transient关键字
在java中,对象一旦实现了Serializable接口,这个对象就可以被序列化,同理,其方法和属性都会被自动序列化。而有时候我们不希望其中的某些属性被序列化【如密码,卡号等】,这时候只要在该属性前面加上transient关键字,就可以标识该属性不需要序列化,当对象序列化时不会序列化该属性。
transient不能被用在方法上。且如果标识的属性是一个对象,该对象必须也实现了Serializable接口
测试效果:
public class JavaTest {
/**
* 测试transient关键字【指定某个属性不被序列化】
*/
@Test
public void testTransient(){
User user = new User();
user.setAge(20);
user.setName("test");
user.setPassword("123456");
System.out.println("序列化之前:"+user);
// 使用阿里的fastJson序列化对象
String userJsonString = JSON.toJSONString(user);
System.out.println("序列化结果:"+userJsonString);
// 使用阿里的fastJson反序列化对象
Object userByJson = JSON.parseObject(userJsonString);
System.out.println("反序列化结果:"+userByJson);
}
/**
* 定义User类实现Serializable接口
*/
// @Data注解来自lombok
@Data
class User implements Serializable{
private String name;
private int age;
private transient String password;
}
}
执行结果: