[关闭]
@xmruibi 2015-02-15T02:23:38.000000Z 字数 8302 阅读 688

Map Interface & AbstractMap

Data_Structure


Map
NOTE that:
1) the difference between key set, value collection and the entry set;

1. Map Interface

  1. //Map接口,K为键值,V为值对象
  2. public interface Map<K,V> {
  3. int size();// elements amount in map
  4. boolean isEmpty();// if the map is empty
  5. boolean containsKey(Object key); // contain key
  6. boolean containsValue(Object value);// contain value
  7. V get(Object key);// return the value by key
  8. V put(K key, V value);// insert key-value map
  9. V remove(Object key);// remove by key
  10. void clear();// clear elements in map
  11. Set<K> keySet(); // the Set(unified key) of Map keys
  12. Collection<V> values(); // the Collection(duplicated allowed) of Map values
  13. /********** Learn more about Entry Set in HashMap ***********/
  14. Set<Map.Entry<K, V>> entrySet(); // return entry set
  15. //Map internal collection, coressponded to an element in map
  16. interface Entry<K,V> {
  17. K getKey(); // return key
  18. V getValue();// return value
  19. V setValue(V value);// set value
  20. boolean equals(Object o);
  21. int hashCode();
  22. }
  23. boolean equals(Object o);
  24. int hashCode();
  25. }

2. AbstractMap

  1. //实现了接口Map
  2. public abstract class AbstractMap<K,V> implements Map<K,V> {
  3. protected AbstractMap() {
  4. }
  5. public int size() {
  6. return entrySet().size();
  7. // get size of set
  8. }
  9. public boolean isEmpty() {
  10. return size() == 0;
  11. }
  12. /********** Based on Iterator **********/
  13. // through iterator to find element with given value
  14. public boolean containsValue(Object value) {
  15. Iterator<Entry<K,V>> i = entrySet().iterator();
  16. if (value==null) { allow value is null
  17. while (i.hasNext()) {
  18. Entry<K,V> e = i.next();
  19. if (e.getValue()==null)
  20. return true;
  21. }
  22. } else {
  23. while (i.hasNext()) {
  24. Entry<K,V> e = i.next();
  25. if (value.equals(e.getValue()))
  26. return true;
  27. }
  28. }
  29. return false;
  30. }
  31. // through iterator to find element with given key
  32. public boolean containsKey(Object key) {
  33. Iterator<Map.Entry<K,V>> i = entrySet().iterator();
  34. if (key==null) {// allow key is null
  35. while (i.hasNext()) {
  36. Entry<K,V> e = i.next();
  37. if (e.getKey()==null)
  38. return true;
  39. }
  40. } else {
  41. while (i.hasNext()) {
  42. Entry<K,V> e = i.next();
  43. if (key.equals(e.getKey()))
  44. return true;
  45. }
  46. }
  47. return false;
  48. }
  49. // get Value by key
  50. public V get(Object key) {
  51. Iterator<Entry<K,V>> i = entrySet().iterator();
  52. if (key==null) {
  53. while (i.hasNext()) {
  54. Entry<K,V> e = i.next();
  55. if (e.getKey()==null)
  56. return e.getValue();
  57. }
  58. } else {
  59. while (i.hasNext()) {
  60. Entry<K,V> e = i.next();
  61. if (key.equals(e.getKey()))
  62. return e.getValue();
  63. }
  64. }
  65. return null;
  66. }
  67. // unimplemented element insert method
  68. public V put(K key, V value) {
  69. throw new UnsupportedOperationException();
  70. }
  71. // Remove the element by key and return its value
  72. public V remove(Object key) {
  73. Iterator<Entry<K,V>> i = entrySet().iterator();//获得迭代器
  74. Entry<K,V> correctEntry = null;
  75. if (key==null) {
  76. while (correctEntry==null && i.hasNext()) {//找到元素
  77. Entry<K,V> e = i.next();
  78. if (e.getKey()==null)
  79. correctEntry = e;
  80. }
  81. } else {
  82. while (correctEntry==null && i.hasNext()) {//找到元素
  83. Entry<K,V> e = i.next();
  84. if (key.equals(e.getKey()))
  85. correctEntry = e;
  86. }
  87. }
  88. V oldValue = null;
  89. if (correctEntry !=null) {
  90. oldValue = correctEntry.getValue();
  91. i.remove();//通过迭代器的remove方法删除
  92. }
  93. return oldValue;
  94. }
  95. // Batch insert by iterative put
  96. public void putAll(Map<? extends K, ? extends V> m) {
  97. for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
  98. put(e.getKey(), e.getValue());
  99. }
  100. public void clear() {
  101. entrySet().clear();
  102. }
  103. /**
  104. * Essentially, volatile is used to indicate that a variable's value will be modified by different threads.
  105. * The volatile keyword in Java is poorly documented, poorly understood, and rarely used!
  106. * The value of this variable will never be cached thread-locally: all reads and writes will go straight to "main memory";
  107. * Access to the variable acts as though it is enclosed in a synchronized block, synchronized on itself.
  108. *
  109. **/
  110. transient volatile Set<K> keySet = null; //key set
  111. transient volatile Collection<V> values = null; //values collection
  112. /****************** The following implementations are for key or value set/collection **********************/
  113. /******************* They all need iterator with anonymous inner iterator class ********************/
  114. /************* They all need iterator with anonymous inner AbstractSet/Collection class **************/
  115. public Set<K> keySet() {
  116. if (keySet == null) {
  117. keySet = new AbstractSet<K>() {// Anonymous Inner Class for Set!!!
  118. public Iterator<K> iterator() {
  119. return new Iterator<K>() {// Anonymous Inner Class for Interator!!!
  120. private Iterator<Entry<K,V>> i = entrySet().iterator();
  121. public boolean hasNext() {
  122. return i.hasNext();
  123. }
  124. public K next() {
  125. return i.next().getKey();
  126. }
  127. public void remove() {
  128. i.remove();
  129. }
  130. };
  131. }
  132. public int size() {
  133. return AbstractMap.this.size();
  134. }
  135. public boolean isEmpty() {
  136. return AbstractMap.this.isEmpty();
  137. }
  138. public void clear() {
  139. AbstractMap.this.clear();
  140. }
  141. public boolean contains(Object k) {
  142. return AbstractMap.this.containsKey(k);
  143. }
  144. };
  145. }
  146. return keySet;
  147. }
  148. public Collection<V> values() {
  149. if (values == null) {
  150. values = new AbstractCollection<V>() {
  151. public Iterator<V> iterator() {
  152. return new Iterator<V>() {
  153. private Iterator<Entry<K,V>> i = entrySet().iterator();
  154. public boolean hasNext() {
  155. return i.hasNext();
  156. }
  157. public V next() {
  158. return i.next().getValue();
  159. }
  160. public void remove() {
  161. i.remove();
  162. }
  163. };
  164. }
  165. public int size() {
  166. return AbstractMap.this.size();
  167. }
  168. public boolean isEmpty() {
  169. return AbstractMap.this.isEmpty();
  170. }
  171. public void clear() {
  172. AbstractMap.this.clear();
  173. }
  174. public boolean contains(Object v) {
  175. return AbstractMap.this.containsValue(v);
  176. }
  177. };
  178. }
  179. return values;
  180. }
  181. // Get Entry Set!
  182. public abstract Set<Entry<K,V>> entrySet();
  183. public boolean equals(Object o) {
  184. if (o == this)
  185. return true;
  186. if (!(o instanceof Map))
  187. return false;
  188. Map<K,V> m = (Map<K,V>) o;
  189. if (m.size() != size())
  190. return false;
  191. try {
  192. Iterator<Entry<K,V>> i = entrySet().iterator();
  193. while (i.hasNext()) {
  194. Entry<K,V> e = i.next();
  195. K key = e.getKey();
  196. V value = e.getValue();
  197. if (value == null) {
  198. if (!(m.get(key)==null && m.containsKey(key))) // ensure the key and value are both matched
  199. return false;
  200. } else {
  201. if (!value.equals(m.get(key)))
  202. return false;
  203. }
  204. }
  205. } catch (ClassCastException unused) {
  206. return false;
  207. } catch (NullPointerException unused) {
  208. return false;
  209. }
  210. return true;
  211. }
  212. /*** the hashcode of a collection means the sum of all hashcode of its elements ***/
  213. public int hashCode() {
  214. int h = 0;
  215. Iterator<Entry<K,V>> i = entrySet().iterator();
  216. while (i.hasNext())
  217. h += i.next().hashCode();
  218. return h;
  219. }
  220. public String toString() {
  221. Iterator<Entry<K,V>> i = entrySet().iterator();
  222. if (! i.hasNext())
  223. return "{}";
  224. StringBuilder sb = new StringBuilder();
  225. sb.append('{');
  226. for (;;) {
  227. Entry<K,V> e = i.next();
  228. K key = e.getKey();
  229. V value = e.getValue();
  230. sb.append(key == this ? "(this Map)" : key);
  231. sb.append('=');
  232. sb.append(value == this ? "(this Map)" : value);
  233. if (! i.hasNext())
  234. return sb.append('}').toString();
  235. sb.append(',').append(' ');
  236. }
  237. }
  238. //Clone new AbstractMap Object
  239. protected Object clone() throws CloneNotSupportedException {
  240. AbstractMap<K,V> result = (AbstractMap<K,V>)super.clone();
  241. // why need to be null???
  242. result.keySet = null;
  243. result.values = null;
  244. return result;
  245. }
  246. private static boolean eq(Object o1, Object o2) {
  247. return o1 == null ? o2 == null : o1.equals(o2);
  248. }
  249. }

3. SimpleEntry

Implementation Note: SimpleEntry and SimpleImmutableEntry are distinct unrelated classes, even though they share some code. Since you can't add or subtract finalness 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.

This class facilitates the process of building custom map implementations.

  1. /**
  2. * Provide some basic implementations by Entry interface
  3. * to get key, get value and set Value...
  4. **/
  5. public static class SimpleEntry<K,V>
  6. implements Entry<K,V>, java.io.Serializable
  7. {
  8. private static final long serialVersionUID = -8499721149061103585L;
  9. private final K key; // key CANNNOT changed
  10. private V value;
  11. /***** Two constructors by providing key, value or an entry object ******/
  12. public SimpleEntry(K key, V value) {
  13. this.key = key;
  14. this.value = value;
  15. }
  16. public SimpleEntry(Entry<? extends K, ? extends V> entry) {
  17. this.key = entry.getKey();
  18. this.value = entry.getValue();
  19. }
  20. public K getKey() {
  21. return key;
  22. }
  23. public V getValue() {
  24. return value;
  25. }
  26. public V setValue(V value) {
  27. V oldValue = this.value;
  28. this.value = value;
  29. return oldValue;
  30. }
  31. public boolean equals(Object o) {
  32. if (!(o instanceof Map.Entry))
  33. return false;
  34. Map.Entry e = (Map.Entry)o;
  35. return eq(key, e.getKey()) && eq(value, e.getValue());
  36. }
  37. public int hashCode() {
  38. // exclusive or between key and value
  39. return (key == null ? 0 : key.hashCode()) ^
  40. (value == null ? 0 : value.hashCode());
  41. }
  42. public String toString() {
  43. return key + "=" + value;
  44. }
  45. }
  46. /******** Only difference is ..SimpleImmutableEntry doesn't support setValue *********/
  47. public static class SimpleImmutableEntry<K,V>
  48. implements Entry<K,V>, java.io.Serializable
  49. {
  50. private static final long serialVersionUID = 7138329143949025153L;
  51. private final K key;
  52. private final V value;
  53. public SimpleImmutableEntry(K key, V value) {
  54. this.key = key;
  55. this.value = value;
  56. }
  57. public SimpleImmutableEntry(Entry<? extends K, ? extends V> entry) {
  58. this.key = entry.getKey();
  59. this.value = entry.getValue();
  60. }
  61. public K getKey() {
  62. return key;
  63. }
  64. public V getValue() {
  65. return value;
  66. }
  67. /****** Note HERE *******/
  68. public V setValue(V value) {
  69. throw new UnsupportedOperationException();
  70. }
  71. public boolean equals(Object o) {
  72. if (!(o instanceof Map.Entry))
  73. return false;
  74. Map.Entry e = (Map.Entry)o;
  75. return eq(key, e.getKey()) && eq(value, e.getValue());
  76. }
  77. public int hashCode() {
  78. return (key == null ? 0 : key.hashCode()) ^
  79. (value == null ? 0 : value.hashCode());
  80. }
  81. public String toString() {
  82. return key + "=" + value;
  83. }
  84. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注