类关系图
功能介绍
包路径: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集合并比较valuewhile (i.hasNext()) {Entry<K,V> e = i.next();if (e.getValue()==null)return true;}} else {// 遍历Entry集合并比较valuewhile (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集合并比较keywhile (i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)return true;}} else {// 遍历Entry集合并比较keywhile (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集合并比较keywhile (i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)return e.getValue();}} else {// 遍历Entry集合并比较keywhile (i.hasNext()) {Entry<K,V> e = i.next();if (key.equals(e.getKey()))return e.getValue();}}// 默认返回nullreturn 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为nullif (key==null) {// 遍历Entry集合,当前entry的key为null时,赋值给correctEntrywhile (correctEntry==null && i.hasNext()) {Entry<K,V> e = i.next();if (e.getKey()==null)correctEntry = e;}} else {// 遍历Entry集合,当前entry的key与目标key相等时,赋值给correctEntrywhile (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为nullif (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即kspublic 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;}// 返回keySetreturn 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类型,直接返回falseif (!(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;
}
}
执行结果:
