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
java] view plain copy <pre name= "code" class= "java"> /** * The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table; //Declared an array ........ public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; threshold = ( int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); table = new Entry[DEFAULT_INITIAL_CAPACITY]; //The size of the initialization array is default_ INITIAL_ Capability (here is 16) init(); }</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
static class Entry<K,V> implements Map. Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; /** * Creates new entry. */ Entry(int h, K k, V v, Entry<K,V> n) { value = v; next = n; key = k; hash = h; } public final K getKey( ) { return key; } public final V getValue( ) { return value; } public final V setValue( V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals( Object o) { if (!(o instanceof Map. Entry)) return false; Map. Entry e = ( Map. Entry)o; Object k1 = getKey(); Object k2 = e. getKey(); if (k1 == k2 || (k1 != null && k1. equals(k2))) { Object v1 = getValue(); Object v2 = e. getValue(); if (v1 == v2 || (v1 != null && v1. equals(v2))) return true; } return false; } public final int hashCode( ) { return (key== null ? 0 : key. hashCode()) ^ (value== null ? 0 : value. hashCode()); } public final String toString( ) { return getKey() + "=" + getValue(); } /** * This method is invoked whenever the value in an entry is * overwritten by an invocation of put(k,v) for a key k that's already * in the HashMap. */ void recordAccess( HashMap<K,V> m) { } /** * This method is invoked whenever the entry is * removed from the table. */ void recordRemoval( HashMap<K,V> m) { } }
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
interface Entry<K,V> { /** * Returns the key corresponding to this entry. * * @return the key corresponding to this entry * @throws IllegalStateException implementations may, but are not * required to, throw this exception if the entry has been * removed from the backing map. */ K getKey(); /** * Returns the value corresponding to this entry. If the mapping * has been removed from the backing map (by the iterator's * <tt>remove</tt> operation), the results of this call are undefined. * * @return the value corresponding to this entry * @throws IllegalStateException implementations may, but are not * required to, throw this exception if the entry has been * removed from the backing map. */ V getValue(); /** * Replaces the value corresponding to this entry with the specified * value (optional operation). (Writes through to the map.) The * behavior of this call is undefined if the mapping has already been * removed from the map (by the iterator's <tt>remove</tt> operation). * * @param value new value to be stored in this entry * @return old value corresponding to the entry * @throws UnsupportedOperationException if the <tt>put</tt> operation * is not supported by the backing map * @throws ClassCastException if the class of the specified value * prevents it from being stored in the backing map * @throws NullPointerException if the backing map does not permit * null values, and the specified value is null * @throws IllegalArgumentException if some property of this value * prevents it from being stored in the backing map * @throws IllegalStateException implementations may, but are not * required to, throw this exception if the entry has been * removed from the backing map. */ V setValue(V value); /** * Compares the specified object with this entry for equality. * Returns <tt>true</tt> if the given object is also a map entry and * the two entries represent the same mapping. More formally, two * entries <tt>e1</tt> and <tt>e2</tt> represent the same mapping * if<pre> * (e1.getKey()==null ? * e2.getKey()==null : e1.getKey().equals(e2.getKey())) && * (e1.getValue()==null ? * e2.getValue()==null : e1.getValue().equals(e2.getValue())) * </pre> * This ensures that the <tt>equals</tt> method works properly across * different implementations of the <tt>Map.Entry</tt> interface. * * @param o object to be compared for equality with this map entry * @return <tt>true</tt> if the specified object is equal to this map * entry */ boolean equals( Object o); /** * Returns the hash code value for this map entry. The hash code * of a map entry <tt>e</tt> is defined to be: <pre> * (e.getKey()==null ? 0 : e.getKey().hashCode()) ^ * (e.getValue()==null ? 0 : e.getValue().hashCode()) * </pre> * This ensures that <tt>e1.equals(e2)</tt> implies that * <tt>e1.hashCode()==e2.hashCode()</tt> for any two Entries * <tt>e1</tt> and <tt>e2</tt>, as required by the general * contract of <tt>Object.hashCode</tt>. * * @return the hash code value for this map entry * @see Object#hashCode() * @see Object#equals(Object) * @see #equals(Object) */ int hashCode(); }
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:
/** * The head of the doubly linked list. */ /Chain head is defined private transient Entry<K,V> header;
How to initialize the linked list:
void init( ) { header = new Entry<K,V>(- 1, null, null, null); header. before = header. after = header; }
TreeMap:
[ java] view plain copy //Define root node private transient Entry<K,V> root = null;
Let's see if his put method looks familiar (insertion operation of binary sort tree)
public V put( K key, V value) { Entry<K,V> t = root; if (t == null) { // TBD: // 5045147: (coll) Adding null to an empty TreeSet should // throw NullPointerException // // compare(key, key); // type check root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr. compare(key, t. key); if (cmp < 0) t = t. left; else if (cmp > 0) t = t. right; else return t. setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = ( Comparable<? super K>) key; do { parent = t; cmp = k. compareTo(t. key); if (cmp < 0) t = t. left; else if (cmp > 0) t = t. right; else return t. setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent. left = e; else parent. right = e; fixAfterInsertion(e); size++; modCount++; return null; }
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
[java] view plain copy 1. Map map = new HashMap(); Irerator iterator = map.entrySet().iterator(); while(iterator.hasNext()) { Map. Entry entry = iterator.next(); Object key = entry.getKey(); // } 2. Map map = new HashMap(); Set keySet= map.keySet(); Irerator iterator = keySet.iterator; while(iterator.hasNext()) { Object key = iterator.next(); Object value = map.get(key); // } 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 [java] view plain copy Map map = new HashMap(); Collection c = map.values(); Iterator iterator = c.iterator(); while(iterator.hasNext()) { Object value = iterator.next();
Original text goes to: https://blog.csdn.net/kyi_zhu123/article/details/52769469