类关系图

AbstractMap - 图1

功能介绍

包路径:java.util

说明:AbstractMap直接实现了Map接口,是一个抽象类,而抽象类通常作为骨架使用,实现一些简单且通用的功能,而核心功能则由子类实现。

AbstractMap是大部分Map接口实现类的父类,典型常用的几个如HashMap、TreeMap、WeakHashMap等。

源码解析

  1. /**
  2. * This class provides a skeletal implementation of the <tt>Map</tt>
  3. * interface, to minimize the effort required to implement this interface.
  4. *
  5. * 此类提供了一个Map接口的骨架实现,以尽可能减少其他类实现Map接口的工作量
  6. *
  7. * @param <K> the type of keys maintained by this map Map映射的key类型
  8. * @param <V> the type of mapped values Map映射的value类型
  9. *
  10. * @author Josh Bloch
  11. * @author Neal Gafter
  12. * @see Map
  13. * @see Collection
  14. * @since 1.2
  15. */
  16. public abstract class AbstractMap<K,V> implements Map<K,V> {
  17. /**
  18. * Sole constructor. (For invocation by subclass constructors, typically
  19. * implicit.)
  20. */
  21. protected AbstractMap() {
  22. }
  23. // Query Operations 检索操作实现
  24. /**
  25. * {@inheritDoc}
  26. *
  27. * @implSpec
  28. * This implementation returns <tt>entrySet().size()</tt>.
  29. */
  30. public int size() {
  31. return entrySet().size(); // 直接返回Map内部维护的Entry实体个数,即映射个数
  32. }
  33. /**
  34. * {@inheritDoc}
  35. *
  36. * @implSpec
  37. * This implementation returns <tt>size() == 0</tt>.
  38. */
  39. public boolean isEmpty() {
  40. return size() == 0;
  41. }
  42. /**
  43. * Map中是否存在目标value
  44. *
  45. * @implSpec
  46. * This implementation iterates over <tt>entrySet()</tt> searching
  47. * for an entry with the specified value. If such an entry is found,
  48. * <tt>true</tt> is returned. If the iteration terminates without
  49. * finding such an entry, <tt>false</tt> is returned. Note that this
  50. * implementation requires linear time in the size of the map.
  51. */
  52. public boolean containsValue(Object value) {
  53. // Entry集合迭代器
  54. Iterator<Entry<K,V>> i = entrySet().iterator();
  55. if (value==null) {
  56. // 遍历Entry集合并比较value
  57. while (i.hasNext()) {
  58. Entry<K,V> e = i.next();
  59. if (e.getValue()==null)
  60. return true;
  61. }
  62. } else {
  63. // 遍历Entry集合并比较value
  64. while (i.hasNext()) {
  65. Entry<K,V> e = i.next();
  66. if (value.equals(e.getValue()))
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. /**
  73. * Map中是否存在目标key对应映射
  74. *
  75. * @implSpec
  76. * This implementation iterates over <tt>entrySet()</tt> searching
  77. * for an entry with the specified key. If such an entry is found,
  78. * <tt>true</tt> is returned. If the iteration terminates without
  79. * finding such an entry, <tt>false</tt> is returned. Note that this
  80. * implementation requires linear time in the size of the map; many
  81. * implementations will override this method.
  82. */
  83. public boolean containsKey(Object key) {
  84. // Entry集合迭代器
  85. Iterator<Map.Entry<K,V>> i = entrySet().iterator();
  86. if (key==null) {
  87. // 遍历Entry集合并比较key
  88. while (i.hasNext()) {
  89. Entry<K,V> e = i.next();
  90. if (e.getKey()==null)
  91. return true;
  92. }
  93. } else {
  94. // 遍历Entry集合并比较key
  95. while (i.hasNext()) {
  96. Entry<K,V> e = i.next();
  97. if (key.equals(e.getKey()))
  98. return true;
  99. }
  100. }
  101. return false;
  102. }
  103. /**
  104. * 据传入的key获取当前映射中对应的value,如果存在对应映射关系,则返回对应值,否则返回null
  105. *
  106. * @implSpec
  107. * This implementation iterates over <tt>entrySet()</tt> searching
  108. * for an entry with the specified key. If such an entry is found,
  109. * the entry's value is returned. If the iteration terminates without
  110. * finding such an entry, <tt>null</tt> is returned. Note that this
  111. * implementation requires linear time in the size of the map; many
  112. * implementations will override this method.
  113. */
  114. public V get(Object key) {
  115. // Entry集合迭代器
  116. Iterator<Entry<K,V>> i = entrySet().iterator();
  117. if (key==null) {
  118. // 遍历Entry集合并比较key
  119. while (i.hasNext()) {
  120. Entry<K,V> e = i.next();
  121. if (e.getKey()==null)
  122. return e.getValue();
  123. }
  124. } else {
  125. // 遍历Entry集合并比较key
  126. while (i.hasNext()) {
  127. Entry<K,V> e = i.next();
  128. if (key.equals(e.getKey()))
  129. return e.getValue();
  130. }
  131. }
  132. // 默认返回null
  133. return null;
  134. }
  135. // Modification Operations 变更操作
  136. /**
  137. * 向当前Map映射中存放键值对,由子类实现
  138. *
  139. * @implSpec
  140. * This implementation always throws an
  141. * <tt>UnsupportedOperationException</tt>.
  142. *
  143. */
  144. public V put(K key, V value) {
  145. throw new UnsupportedOperationException();
  146. }
  147. /**
  148. * 从当前Map映射中移除以目标key为键的映射关系,并返回key对应的value,如果没有映射关系则返回null
  149. *
  150. * @implSpec
  151. * This implementation iterates over <tt>entrySet()</tt> searching for an
  152. * entry with the specified key. If such an entry is found, its value is
  153. * obtained with its <tt>getValue</tt> operation, the entry is removed
  154. * from the collection (and the backing map) with the iterator's
  155. * <tt>remove</tt> operation, and the saved value is returned. If the
  156. * iteration terminates without finding such an entry, <tt>null</tt> is
  157. * returned. Note that this implementation requires linear time in the
  158. * size of the map; many implementations will override this method.
  159. */
  160. public V remove(Object key) {
  161. // Entry集合迭代器
  162. Iterator<Entry<K,V>> i = entrySet().iterator();
  163. // 定义目标Entry,即目标映射对象
  164. Entry<K,V> correctEntry = null;
  165. // 如果key为null
  166. if (key==null) {
  167. // 遍历Entry集合,当前entry的key为null时,赋值给correctEntry
  168. while (correctEntry==null && i.hasNext()) {
  169. Entry<K,V> e = i.next();
  170. if (e.getKey()==null)
  171. correctEntry = e;
  172. }
  173. } else {
  174. // 遍历Entry集合,当前entry的key与目标key相等时,赋值给correctEntry
  175. while (correctEntry==null && i.hasNext()) {
  176. Entry<K,V> e = i.next();
  177. if (key.equals(e.getKey()))
  178. correctEntry = e;
  179. }
  180. }
  181. // 获取目标映射的值并删除映射
  182. V oldValue = null;
  183. if (correctEntry !=null) {
  184. oldValue = correctEntry.getValue();
  185. i.remove();
  186. }
  187. // 目标映射的值
  188. return oldValue;
  189. }
  190. // Bulk Operations 扩展操作
  191. /**
  192. * 从指定的map中拷贝所有的映射到该map中
  193. *
  194. * @implSpec
  195. * This implementation iterates over the specified map's
  196. * <tt>entrySet()</tt> collection, and calls this map's <tt>put</tt>
  197. * operation once for each entry returned by the iteration.
  198. */
  199. public void putAll(Map<? extends K, ? extends V> m) {
  200. // 遍历m中的Entry集合
  201. for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
  202. // 拷贝映射
  203. put(e.getKey(), e.getValue());
  204. }
  205. /**
  206. * 清空当前Map所有映射
  207. *
  208. * @implSpec
  209. * This implementation calls <tt>entrySet().clear()</tt>.
  210. *
  211. * <p>Note that this implementation throws an
  212. * <tt>UnsupportedOperationException</tt> if the <tt>entrySet</tt>
  213. * does not support the <tt>clear</tt> operation.
  214. *
  215. * @throws UnsupportedOperationException {@inheritDoc}
  216. */
  217. public void clear() {
  218. entrySet().clear(); // Set集合的Clear方法
  219. }
  220. // Views 视图
  221. /**
  222. * Each of these fields are initialized to contain an instance of the
  223. * appropriate view the first time this view is requested. The views are
  224. * stateless, so there's no reason to create more than one of each.
  225. *
  226. * transient关键字防止被序列化
  227. */
  228. transient Set<K> keySet; // 存储所有key的set集合
  229. transient Collection<V> values; // 存储所有value的集合
  230. /**
  231. * 返回key的set集合
  232. *
  233. * @implSpec
  234. * This implementation returns a set that subclasses {@link AbstractSet}.
  235. * The subclass's iterator method returns a "wrapper object" over this
  236. * map's <tt>entrySet()</tt> iterator. The <tt>size</tt> method
  237. * delegates to this map's <tt>size</tt> method and the
  238. * <tt>contains</tt> method delegates to this map's
  239. * <tt>containsKey</tt> method.
  240. */
  241. public Set<K> keySet() {
  242. Set<K> ks = keySet;
  243. // 如果当前keySet为null
  244. if (ks == null) {
  245. // 构建一个AbstractSet,以Map的key类型为泛型参数,即key的set集合
  246. ks = new AbstractSet<K>() {
  247. // 定义AbstractSet的迭代器
  248. public Iterator<K> iterator() {
  249. return new Iterator<K>() {
  250. // Entry的set集合迭代器
  251. private Iterator<Entry<K,V>> i = entrySet().iterator();
  252. public boolean hasNext() {
  253. return i.hasNext();
  254. }
  255. public K next() {
  256. return i.next().getKey();
  257. }
  258. public void remove() {
  259. i.remove();
  260. }
  261. };
  262. }
  263. // AbstractMap.this即ks
  264. public int size() {
  265. return AbstractMap.this.size();
  266. }
  267. public boolean isEmpty() {
  268. return AbstractMap.this.isEmpty();
  269. }
  270. public void clear() {
  271. AbstractMap.this.clear();
  272. }
  273. public boolean contains(Object k) {
  274. return AbstractMap.this.containsKey(k);
  275. }
  276. };
  277. keySet = ks;
  278. }
  279. // 返回keySet
  280. return ks;
  281. }
  282. /**
  283. * 获取value集合
  284. *
  285. * @implSpec
  286. * This implementation returns a collection that subclasses {@link
  287. * AbstractCollection}. The subclass's iterator method returns a
  288. * "wrapper object" over this map's <tt>entrySet()</tt> iterator.
  289. * The <tt>size</tt> method delegates to this map's <tt>size</tt>
  290. * method and the <tt>contains</tt> method delegates to this map's
  291. * <tt>containsValue</tt> method.
  292. *
  293. */
  294. public Collection<V> values() {
  295. Collection<V> vals = values;
  296. if (vals == null) {
  297. // 构建匿名内部AbstractCollection,以Map的value类型为泛型参数,即value的列表
  298. vals = new AbstractCollection<V>() {
  299. // 迭代器方法
  300. public Iterator<V> iterator() {
  301. // 构建内部迭代器
  302. return new Iterator<V>() {
  303. private Iterator<Entry<K,V>> i = entrySet().iterator();
  304. public boolean hasNext() {
  305. return i.hasNext();
  306. }
  307. public V next() {
  308. return i.next().getValue();
  309. }
  310. public void remove() {
  311. i.remove();
  312. }
  313. };
  314. }
  315. public int size() {
  316. return AbstractMap.this.size();
  317. }
  318. public boolean isEmpty() {
  319. return AbstractMap.this.isEmpty();
  320. }
  321. public void clear() {
  322. AbstractMap.this.clear();
  323. }
  324. public boolean contains(Object v) {
  325. return AbstractMap.this.containsValue(v);
  326. }
  327. };
  328. values = vals;
  329. }
  330. return vals;
  331. }
  332. // 返回该map中所有映射的Set视图。由子类实现
  333. public abstract Set<Entry<K,V>> entrySet();
  334. // Comparison and hashing
  335. /**
  336. * 比较两个Map,如果两个Map映射完全一样【ker和value完全一致】,返回true
  337. *
  338. * @param o object to be compared for equality with this map
  339. * @return <tt>true</tt> if the specified object is equal to this map
  340. */
  341. public boolean equals(Object o) {
  342. // 如果就是本对象
  343. if (o == this)
  344. return true;
  345. // 如果传入对象不是Map类型,直接返回false
  346. if (!(o instanceof Map))
  347. return false;
  348. // 强转
  349. Map<?,?> m = (Map<?,?>) o;
  350. // 先比较记录数
  351. if (m.size() != size())
  352. return false;
  353. try {
  354. // Entry集合迭代器
  355. Iterator<Entry<K,V>> i = entrySet().iterator();
  356. while (i.hasNext()) {
  357. // 比对当前Entry与传入Map对应key的映射是否一致
  358. Entry<K,V> e = i.next();
  359. K key = e.getKey();
  360. V value = e.getValue();
  361. if (value == null) {
  362. if (!(m.get(key)==null && m.containsKey(key)))
  363. return false;
  364. } else {
  365. if (!value.equals(m.get(key)))
  366. return false;
  367. }
  368. }
  369. } catch (ClassCastException unused) {
  370. return false;
  371. } catch (NullPointerException unused) {
  372. return false;
  373. }
  374. return true;
  375. }
  376. /**
  377. *
  378. * @return the hash code value for this map
  379. * @see Map.Entry#hashCode()
  380. * @see Object#equals(Object)
  381. * @see Set#equals(Object)
  382. */
  383. public int hashCode() {
  384. int h = 0;
  385. Iterator<Entry<K,V>> i = entrySet().iterator();
  386. while (i.hasNext())
  387. h += i.next().hashCode();
  388. return h;
  389. }
  390. /**
  391. *
  392. * @return a string representation of this map
  393. */
  394. public String toString() {
  395. Iterator<Entry<K,V>> i = entrySet().iterator();
  396. if (! i.hasNext())
  397. return "{}";
  398. StringBuilder sb = new StringBuilder();
  399. sb.append('{');
  400. for (;;) {
  401. Entry<K,V> e = i.next();
  402. K key = e.getKey();
  403. V value = e.getValue();
  404. sb.append(key == this ? "(this Map)" : key);
  405. sb.append('=');
  406. sb.append(value == this ? "(this Map)" : value);
  407. if (! i.hasNext())
  408. return sb.append('}').toString();
  409. sb.append(',').append(' ');
  410. }
  411. }
  412. /**
  413. * Returns a shallow copy of this <tt>AbstractMap</tt> instance: the keys
  414. * and values themselves are not cloned.
  415. *
  416. * @return a shallow copy of this map
  417. */
  418. protected Object clone() throws CloneNotSupportedException {
  419. AbstractMap<?,?> result = (AbstractMap<?,?>)super.clone();
  420. result.keySet = null;
  421. result.values = null;
  422. return result;
  423. }
  424. /**
  425. * Utility method for SimpleEntry and SimpleImmutableEntry.
  426. * Test for equality, checking for nulls.
  427. *
  428. * NB: Do not replace with Object.equals until JDK-8015417 is resolved.
  429. */
  430. private static boolean eq(Object o1, Object o2) {
  431. return o1 == null ? o2 == null : o1.equals(o2);
  432. }
  433. // Implementation Note: SimpleEntry and SimpleImmutableEntry
  434. // are distinct unrelated classes, even though they share
  435. // some code. Since you can't add or subtract final-ness
  436. // of a field in a subclass, they can't share representations,
  437. // and the amount of duplicated code is too small to warrant
  438. // exposing a common abstract class.
  439. /**
  440. * Map中内部接口Entry的简单实现
  441. *
  442. * @since 1.6
  443. */
  444. public static class SimpleEntry<K,V>
  445. implements Entry<K,V>, java.io.Serializable
  446. {
  447. private static final long serialVersionUID = -8499721149061103585L;
  448. private final K key;
  449. private V value;
  450. /**
  451. * Creates an entry representing a mapping from the specified
  452. * key to the specified value.
  453. *
  454. * @param key the key represented by this entry
  455. * @param value the value represented by this entry
  456. */
  457. public SimpleEntry(K key, V value) {
  458. this.key = key;
  459. this.value = value;
  460. }
  461. /**
  462. * Creates an entry representing the same mapping as the
  463. * specified entry.
  464. *
  465. * @param entry the entry to copy
  466. */
  467. public SimpleEntry(Entry<? extends K, ? extends V> entry) {
  468. this.key = entry.getKey();
  469. this.value = entry.getValue();
  470. }
  471. /**
  472. * Returns the key corresponding to this entry.
  473. *
  474. * @return the key corresponding to this entry
  475. */
  476. public K getKey() {
  477. return key;
  478. }
  479. /**
  480. * Returns the value corresponding to this entry.
  481. *
  482. * @return the value corresponding to this entry
  483. */
  484. public V getValue() {
  485. return value;
  486. }
  487. /**
  488. * Replaces the value corresponding to this entry with the specified
  489. * value.
  490. *
  491. * @param value new value to be stored in this entry
  492. * @return the old value corresponding to the entry
  493. */
  494. public V setValue(V value) {
  495. V oldValue = this.value;
  496. this.value = value;
  497. return oldValue;
  498. }
  499. /**
  500. *
  501. * @param o object to be compared for equality with this map entry
  502. * @return {@code true} if the specified object is equal to this map
  503. * entry
  504. * @see #hashCode
  505. */
  506. public boolean equals(Object o) {
  507. if (!(o instanceof Map.Entry))
  508. return false;
  509. Map.Entry<?,?> e = (Map.Entry<?,?>)o;
  510. return eq(key, e.getKey()) && eq(value, e.getValue());
  511. }
  512. /**
  513. *
  514. * @return the hash code value for this map entry
  515. * @see #equals
  516. */
  517. public int hashCode() {
  518. return (key == null ? 0 : key.hashCode()) ^
  519. (value == null ? 0 : value.hashCode());
  520. }
  521. /**
  522. * Returns a String representation of this map entry. This
  523. * implementation returns the string representation of this
  524. * entry's key followed by the equals character ("<tt>=</tt>")
  525. * followed by the string representation of this entry's value.
  526. *
  527. * @return a String representation of this map entry
  528. */
  529. public String toString() {
  530. return key + "=" + value;
  531. }
  532. }
  533. /**
  534. * Entry接口的实现类,但entry对象是不可改变的,即key和value确定后,不能更改
  535. *
  536. * @since 1.6
  537. */
  538. public static class SimpleImmutableEntry<K,V>
  539. implements Entry<K,V>, java.io.Serializable
  540. {
  541. private static final long serialVersionUID = 7138329143949025153L;
  542. private final K key;
  543. private final V value;
  544. /**
  545. * Creates an entry representing a mapping from the specified
  546. * key to the specified value.
  547. *
  548. * @param key the key represented by this entry
  549. * @param value the value represented by this entry
  550. */
  551. public SimpleImmutableEntry(K key, V value) {
  552. this.key = key;
  553. this.value = value;
  554. }
  555. /**
  556. * Creates an entry representing the same mapping as the
  557. * specified entry.
  558. *
  559. * @param entry the entry to copy
  560. */
  561. public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
  562. this.key = entry.getKey();
  563. this.value = entry.getValue();
  564. }
  565. /**
  566. * Returns the key corresponding to this entry.
  567. *
  568. * @return the key corresponding to this entry
  569. */
  570. public K getKey() {
  571. return key;
  572. }
  573. /**
  574. * Returns the value corresponding to this entry.
  575. *
  576. * @return the value corresponding to this entry
  577. */
  578. public V getValue() {
  579. return value;
  580. }
  581. /**
  582. * value仅能通过初始创建即设置,不能进行修改,抛出异常
  583. */
  584. public V setValue(V value) {
  585. throw new UnsupportedOperationException();
  586. }
  587. /**
  588. *
  589. * @param o object to be compared for equality with this map entry
  590. * @return {@code true} if the specified object is equal to this map
  591. * entry
  592. * @see #hashCode
  593. */
  594. public boolean equals(Object o) {
  595. if (!(o instanceof Map.Entry))
  596. return false;
  597. Map.Entry<?,?> e = (Map.Entry<?,?>)o;
  598. return eq(key, e.getKey()) && eq(value, e.getValue());
  599. }
  600. /**
  601. *
  602. * @return the hash code value for this map entry
  603. * @see #equals
  604. */
  605. public int hashCode() {
  606. return (key == null ? 0 : key.hashCode()) ^
  607. (value == null ? 0 : value.hashCode());
  608. }
  609. /**
  610. *
  611. * @return a String representation of this map entry
  612. */
  613. public String toString() {
  614. return key + "=" + value;
  615. }
  616. }
  617. }

总结

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;
   }
}

执行结果:
image.png