Four methods of traversing map

Keywords: Java

  Map.entrySet() returns a Set < map. Entry < K, V > >. Map. Entry is an interface in map. Its purpose is to represent a mapping item (with Key and Value), and Set < map. Entry < K, V > > represents the Set of a mapping item. There are corresponding getKey and getValue methods in Map.Entry, namely JavaBean, so that we can get Key and Value from an item.

 

Here are four ways to traverse the Map:

public static void main(String[] args) {
 
 
  Map<String, String> map = new HashMap<String, String>();
  map.put("1", "value1");
  map.put("2", "value2");
  map.put("3", "value3");
  
  // The first type: commonly used, secondary value
  System.out.println("traverse key and value:") through Map.keySet);
  for (String key : map.keySet()) {
   System.out.println("key= "+ key + " and value= " + map.get(key));
  }
  
  // Second
  System.out.println("use iterator to traverse key and value:") through Map.entrySet);
  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
  while (it.hasNext()) {
   Map.Entry<String, String> entry = it.next();
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  }
  
  // Third: recommended, especially when the capacity is large
  System.out.println("traverse key and value through Map.entrySet");
  for (Map.Entry<String, String> entry : map.entrySet()) {
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  }
 
  // Fourth
  System.out.println("traverse all value s through Map.values(), but not key s");
  for (String v : map.values()) {
   System.out.println("value= " + v);
  }
 }


The following is the source code of HashMap:

First, the underlying implementation of HashMap uses an Entry array

   
  1. java] view plain copy
  2. <pre name= "code" class= "java"> /**
  3. * The table, resized as necessary. Length MUST Always be a power of two.
  4. */
  5. transient Entry[] table; //Declared an array
  6. ........
  7. public HashMap() {
  8. this.loadFactor = DEFAULT_LOAD_FACTOR;
  9. threshold = ( int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
  10. table = new Entry[DEFAULT_INITIAL_CAPACITY]; //The size of the initialization array is default_ INITIAL_ Capability (here is 16)
  11. init();
  12. }</pre><br>


Let's see where Entry is defined. Continue with the source code. We found its definition in line 674 of the source code of HashMap. It turns out that it is an internal class of HashMap and implements the Map.Entry interface. Some of the following are reproduced

 

   
  1. static class Entry<K,V> implements Map. Entry<K,V> {
  2. final K key;
  3. V value;
  4. Entry<K,V> next;
  5. final int hash;
  6. /**
  7. * Creates new entry.
  8. */
  9. Entry(int h, K k, V v, Entry<K,V> n) {
  10. value = v;
  11. next = n;
  12. key = k;
  13. hash = h;
  14. }
  15. public final K getKey( ) {
  16. return key;
  17. }
  18. public final V getValue( ) {
  19. return value;
  20. }
  21. public final V setValue( V newValue) {
  22. V oldValue = value;
  23. value = newValue;
  24. return oldValue;
  25. }
  26. public final boolean equals( Object o) {
  27. if (!(o instanceof Map. Entry))
  28. return false;
  29. Map. Entry e = ( Map. Entry)o;
  30. Object k1 = getKey();
  31. Object k2 = e. getKey();
  32. if (k1 == k2 || (k1 != null && k1. equals(k2))) {
  33. Object v1 = getValue();
  34. Object v2 = e. getValue();
  35. if (v1 == v2 || (v1 != null && v1. equals(v2)))
  36. return true;
  37. }
  38. return false;
  39. }
  40. public final int hashCode( ) {
  41. return (key== null ? 0 : key. hashCode()) ^
  42. (value== null ? 0 : value. hashCode());
  43. }
  44. public final String toString( ) {
  45. return getKey() + "=" + getValue();
  46. }
  47. /**
  48. * This method is invoked whenever the value in an entry is
  49. * overwritten by an invocation of put(k,v) for a key k that's already
  50. * in the HashMap.
  51. */
  52. void recordAccess( HashMap<K,V> m) {
  53. }
  54. /**
  55. * This method is invoked whenever the entry is
  56. * removed from the table.
  57. */
  58. void recordRemoval( HashMap<K,V> m) {
  59. }
  60. }

 

In that case, let's take a look at how the Map.Entry interface is defined. It turns out that it is an internal interface of Map and defines some methods

   
  1. interface Entry<K,V> {
  2. /**
  3. * Returns the key corresponding to this entry.
  4. *
  5. * @return the key corresponding to this entry
  6. * @throws IllegalStateException implementations may, but are not
  7. * required to, throw this exception if the entry has been
  8. * removed from the backing map.
  9. */
  10. K getKey();
  11. /**
  12. * Returns the value corresponding to this entry. If the mapping
  13. * has been removed from the backing map (by the iterator's
  14. * <tt>remove</tt> operation), the results of this call are undefined.
  15. *
  16. * @return the value corresponding to this entry
  17. * @throws IllegalStateException implementations may, but are not
  18. * required to, throw this exception if the entry has been
  19. * removed from the backing map.
  20. */
  21. V getValue();
  22. /**
  23. * Replaces the value corresponding to this entry with the specified
  24. * value (optional operation). (Writes through to the map.) The
  25. * behavior of this call is undefined if the mapping has already been
  26. * removed from the map (by the iterator's <tt>remove</tt> operation).
  27. *
  28. * @param value new value to be stored in this entry
  29. * @return old value corresponding to the entry
  30. * @throws UnsupportedOperationException if the <tt>put</tt> operation
  31. * is not supported by the backing map
  32. * @throws ClassCastException if the class of the specified value
  33. * prevents it from being stored in the backing map
  34. * @throws NullPointerException if the backing map does not permit
  35. * null values, and the specified value is null
  36. * @throws IllegalArgumentException if some property of this value
  37. * prevents it from being stored in the backing map
  38. * @throws IllegalStateException implementations may, but are not
  39. * required to, throw this exception if the entry has been
  40. * removed from the backing map.
  41. */
  42. V setValue(V value);
  43. /**
  44. * Compares the specified object with this entry for equality.
  45. * Returns <tt>true</tt> if the given object is also a map entry and
  46. * the two entries represent the same mapping. More formally, two
  47. * entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping
  48. * if<pre>
  49. * (e1.getKey()==null ?
  50. * e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
  51. * (e1.getValue()==null ?
  52. * e2.getValue()==null : e1.getValue().equals(e2.getValue()))
  53. * </pre>
  54. * This ensures that the <tt>equals</tt> method works properly across
  55. * different implementations of the <tt>Map.Entry</tt> interface.
  56. *
  57. * @param o object to be compared for equality with this map entry
  58. * @return <tt>true</tt> if the specified object is equal to this map
  59. * entry
  60. */
  61. boolean equals( Object o);
  62. /**
  63. * Returns the hash code value for this map entry. The hash code
  64. * of a map entry <tt>e</tt> is defined to be: <pre>
  65. * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
  66. * (e.getValue()==null ? 0 : e.getValue().hashCode())
  67. * </pre>
  68. * This ensures that <tt>e1.equals(e2)</tt> implies that
  69. * <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries
  70. * <tt>e1</tt> and <tt>e2</tt>, as required by the general
  71. * contract of <tt>Object.hashCode</tt>.
  72. *
  73. * @return the hash code value for this map entry
  74. * @see Object#hashCode()
  75. * @see Object#equals(Object)
  76. * @see #equals(Object)
  77. */
  78. int hashCode();
  79. }

 


      When you see here, you probably understand why HashMap chooses the Entry array to store key values. Right, because the Map.Entry interface implemented by Entry defines getKey(),getValue(), setKey(),setValue() and other methods, which are equivalent to a javaBean, encapsulating key value pairs for later operations, In fact, we can also think of not only HashMap, such as LinkedHashMap,TreeMap and other containers inherited from map. The storage key value pairs should use Entry, but the form of organizing Entry is different. HashMap uses the form of array and linked list, LinkedHashMap uses the form of linked list, and TreeMap should use the form of binary tree. If you don't believe it, please refer to the source code

 

LinkedHashMap:​​​​​​​

   
  1. /**
  2. * The head of the doubly linked list.
  3. */
  4. /Chain head is defined
  5. private transient Entry<K,V> header;

 


How to initialize the linked list:

   
  1. void init( ) {
  2. header = new Entry<K,V>(- 1, null, null, null);
  3. header. before = header. after = header;
  4. }

​​​​​​

TreeMap:

   
  1. [ java] view plain copy
  2. //Define root node
  3. private transient Entry<K,V> root = null;

​​​​​​​

Let's see if his put method looks familiar (insertion operation of binary sort tree)

   
  1. public V put( K key, V value) {
  2. Entry<K,V> t = root;
  3. if (t == null) {
  4. // TBD:
  5. // 5045147: (coll) Adding null to an empty TreeSet should
  6. // throw NullPointerException
  7. //
  8. // compare(key, key); // type check
  9. root = new Entry<K,V>(key, value, null);
  10. size = 1;
  11. modCount++;
  12. return null;
  13. }
  14. int cmp;
  15. Entry<K,V> parent;
  16. // split comparator and comparable paths
  17. Comparator<? super K> cpr = comparator;
  18. if (cpr != null) {
  19. do {
  20. parent = t;
  21. cmp = cpr. compare(key, t. key);
  22. if (cmp < 0)
  23. t = t. left;
  24. else if (cmp > 0)
  25. t = t. right;
  26. else
  27. return t. setValue(value);
  28. } while (t != null);
  29. }
  30. else {
  31. if (key == null)
  32. throw new NullPointerException();
  33. Comparable<? super K> k = ( Comparable<? super K>) key;
  34. do {
  35. parent = t;
  36. cmp = k. compareTo(t. key);
  37. if (cmp < 0)
  38. t = t. left;
  39. else if (cmp > 0)
  40. t = t. right;
  41. else
  42. return t. setValue(value);
  43. } while (t != null);
  44. }
  45. Entry<K,V> e = new Entry<K,V>(key, value, parent);
  46. if (cmp < 0)
  47. parent. left = e;
  48. else
  49. parent. right = e;
  50. fixAfterInsertion(e);
  51. size++;
  52. modCount++;
  53. return null;
  54. }

 


ok, after understanding the way in which key value pairs are stored at the bottom of various maps, let's take a look at how to traverse maps. Here's a demonstration with HashMap

 

  Map provides some common methods, such as keySet(), entryset (). The return value of keySet() method is the Set of key values in map; The return value of entrySet() also returns a Set set. The type of this Set is Map.Entry.

so, it is easy to write the following traversal code

   
  1. [java] view plain copy
  2. 1. Map map = new HashMap();
  3. Irerator iterator = map.entrySet().iterator();
  4. while(iterator.hasNext()) {
  5. Map. Entry entry = iterator.next();
  6. Object key = entry.getKey();
  7. //
  8. }
  9. 2. Map map = new HashMap();
  10. Set keySet= map.keySet();
  11. Irerator iterator = keySet.iterator;
  12. while(iterator.hasNext()) {
  13. Object key = iterator.next();
  14. Object value = map.get(key);
  15. //
  16. }
  17. In addition, another traversal method is simple traversal value Value, Map There is one values Method returns value of Collection Set. By traversal collection You can also traverse value,as
  18. [java] view plain copy
  19. Map map = new HashMap();
  20. Collection c = map.values();
  21. Iterator iterator = c.iterator();
  22. while(iterator.hasNext()) {
  23. Object value = iterator.next();

 


Original text goes to: https://blog.csdn.net/kyi_zhu123/article/details/52769469

Posted by silentmajority3 on Sun, 31 Oct 2021 21:58:52 -0700