HashMap的keyset与value的对应

来源:互联网 发布:青岛阿里云联系方式 编辑:程序博客网 时间:2024/05/05 17:22
Map怎么确保得values()和keyset()的顺序是一样的呢?

原来用map都是先取key然后得到value。由于在map上封装了,不能直接取得entryset,只有keyset和values(),getValue(key)。那values()和keyset()中的元素顺序是否对应呢?

首先,写个test,看看顺序是不是一致的:

Java代码 复制代码 收藏代码
  1. public class HashMapOrder {  
  2.       
  3.     public staticvoid main(String[] args) {  
  4.         HashMap map = new HashMap();  
  5.           
  6. //      map.put(1, "E");  
  7. //      map.put(2, "D");  
  8. //      map.put(3, "C");  
  9. //      map.put(4, "B");  
  10. //      map.put(5, "A");  
  11.  
  12.         map.put(12,"E");  
  13.         map.put(2,"D");  
  14.         map.put(31,"C");  
  15.         map.put(4,"B");  
  16.         map.put(56,"A");  
  17.           
  18.         for(Object key:map.keySet())  
  19.             System.out.print(key + ", ");  
  20.           
  21.         System.out.println();  
  22.           
  23.         for(Object value:map.values())  
  24.             System.out.print(value+", ");  
  25.           
  26.     }  
  27.  
[java] view plaincopyprint?
  1. public class HashMapOrder { 
  2.      
  3.     public staticvoid main(String[] args) { 
  4.         HashMap map = new HashMap(); 
  5.          
  6. //      map.put(1, "E"); 
  7. //      map.put(2, "D"); 
  8. //      map.put(3, "C"); 
  9. //      map.put(4, "B"); 
  10. //      map.put(5, "A"); 
  11.  
  12.         map.put(12, "E"); 
  13.         map.put(2, "D"); 
  14.         map.put(31, "C"); 
  15.         map.put(4, "B"); 
  16.         map.put(56, "A"); 
  17.          
  18.         for(Object key:map.keySet()) 
  19.             System.out.print(key + ", "); 
  20.          
  21.         System.out.println(); 
  22.          
  23.         for(Object value:map.values()) 
  24.             System.out.print(value+", "); 
  25.          
  26.     } 
  27.  

发现没问题,第一个注释了的代码数据是有序的。输出

1, 2, 3, 4, 5,

E, D, C, B, A,

第二个无序数据输出:

2, 4, 56, 12, 31,

D, B, A, E, C,

也正常!

没问题,查看代码理解如下:

HashMap中存储数据的对象本质是有一个数组!使用Entry[]保存keyvalue对,  然后如果是一样的index会以链表的形式加在entry的next上。

keyset()和value()返回的都是匿名内部类对象,使用iterator迭代器对table的一个迭代!

首先,说明entryset()的来龙气脉,后面values()和keyset()都会用到这个方法。

java.util.HashMap.entrySet()

Java代码 复制代码 收藏代码
  1. public Set<Map.Entry<K,V>> entrySet() {  
  2.     return entrySet0();  
  3. }  
  4.  
  5. private Set<Map.Entry<K,V>> entrySet0() {  
  6.     Set<Map.Entry<K,V>> es = entrySet;  
  7.     return es != null ? es : (entrySet =new EntrySet());  
  8. }  
  9. // 内部类,没有static!  
  10. private finalclass EntrySet extends AbstractSet<Map.Entry<K,V>> {  
  11.     public Iterator<Map.Entry<K,V>> iterator() {  
  12.         return newEntryIterator();//!!! 
  13.     }  
  14.     public boolean contains(Object o) {  
  15.         if (!(o instanceof Map.Entry))  
  16.             return false;  
  17.         Map.Entry<K,V> e = (Map.Entry<K,V>) o;  
  18.         Entry<K,V> candidate = getEntry(e.getKey()); // !!! 
  19.         return candidate != null && candidate.equals(e);  
  20.     }  
  21.     public boolean remove(Object o) {  
  22.         return removeMapping(o) !=null;  
  23.     }  
  24.     public int size() {  
  25.         return size;  
  26.     }  
  27.     public void clear() {  
  28.         HashMap.this.clear();  
  29.     }  
[java] view plaincopyprint?
  1. public Set<Map.Entry<K,V>> entrySet() { 
  2.     return entrySet0(); 
  3.  
  4. private Set<Map.Entry<K,V>> entrySet0() { 
  5.     Set<Map.Entry<K,V>> es = entrySet; 
  6.     return es != null ? es : (entrySet = new EntrySet()); 
  7. // 内部类,没有static! 
  8. private finalclass EntrySet extends AbstractSet<Map.Entry<K,V>> { 
  9.     public Iterator<Map.Entry<K,V>> iterator() { 
  10.         return newEntryIterator(); //!!! 
  11.     } 
  12.     public boolean contains(Object o) { 
  13.         if (!(o instanceof Map.Entry)) 
  14.             return false
  15.         Map.Entry<K,V> e = (Map.Entry<K,V>) o; 
  16.         Entry<K,V> candidate = getEntry(e.getKey()); // !!! 
  17.         return candidate !=null && candidate.equals(e); 
  18.     } 
  19.     public boolean remove(Object o) { 
  20.         return removeMapping(o) != null
  21.     } 
  22.     public int size() { 
  23.         return size; 
  24.     } 
  25.     public void clear() { 
  26.         HashMap.this.clear(); 
  27.     } 

java.util.HashMap.getEntry(Object)

Java代码 复制代码 收藏代码
  1. final Entry<K,V> getEntry(Object key) {  
  2.     int hash = (key == null) ? 0 : hash(key.hashCode());  
  3.     for (Entry<K,V> e = table[indexFor(hash, table.length)];  
  4.          e != null;  
  5.          e = e.next) {  
  6.         Object k;  
  7.         if (e.hash == hash &&  
  8.             ((k = e.key) == key || (key != null && key.equals(k))))  
  9.             return e;  
  10.     }  
  11.     return null;  
[java] view plaincopyprint?
  1. final Entry<K,V> getEntry(Object key) { 
  2.     int hash = (key == null) ?0 : hash(key.hashCode()); 
  3.     for (Entry<K,V> e = table[indexFor(hash, table.length)]; 
  4.          e != null
  5.          e = e.next) { 
  6.         Object k; 
  7.         if (e.hash == hash && 
  8.             ((k = e.key) == key || (key != null && key.equals(k)))) 
  9.             return e; 
  10.     } 
  11.     return null

Java代码 复制代码 收藏代码
  1.     Iterator<Map.Entry<K,V>> newEntryIterator()   {  
  2.         return new EntryIterator();  
  3.     }  
  4.  
  5.     private finalclass EntryIterator extends HashIterator<Map.Entry<K,V>> {  
  6.         public Map.Entry<K,V> next() {  
  7.             return nextEntry();  
  8.         }  
  9.     }  
  10.  
  11. java.util.HashMap.HashIterator.nextEntry()  
  12.     。。。。。。 
[java] view plaincopyprint?
  1.     Iterator<Map.Entry<K,V>> newEntryIterator()   { 
  2.         return new EntryIterator(); 
  3.     } 
  4.  
  5.     private finalclass EntryIterator extends HashIterator<Map.Entry<K,V>> { 
  6.         public Map.Entry<K,V> next() { 
  7.             return nextEntry(); 
  8.         } 
  9.     } 
  10.  
  11. java.util.HashMap.HashIterator.nextEntry() 
  12.     。。。。。。 

再来看keyset()和value()方法,通过iterator迭代entrySet,即获取Entry[]数组中的元素,然后分别取对应的key和value:

java.util.AbstractMap.keySet()

Java代码 复制代码 收藏代码
  1. public Set<K> keySet() {  
  2.     if (keySet == null) {  
  3.         keySet = new AbstractSet<K>() {  
  4.             public Iterator<K> iterator() {  
  5.                 return new Iterator<K>() {  
  6.                     private Iterator<Entry<K,V>> i = entrySet().iterator();  
  7.  
  8.                     public boolean hasNext() {  
  9.                         return i.hasNext();  
  10.                     }  
  11.  
  12.                     public K next() {  
  13.                         return i.next().getKey();//!!! 
  14.                     }  
  15.  
  16.                     public void remove() {  
  17.                         i.remove();  
  18.                     }  
  19.                 };  
  20.             }  
  21.  
  22.             public int size() {  
  23.                 return AbstractMap.this.size();  
  24.             }  
  25.  
  26.             public boolean isEmpty() {  
  27.                 return AbstractMap.this.isEmpty();  
  28.             }  
  29.  
  30.             public void clear() {  
  31.                 AbstractMap.this.clear();  
  32.             }  
  33.  
  34.             public boolean contains(Object k) {  
  35.                 return AbstractMap.this.containsKey(k);  
  36.             }  
  37.         };  
  38.     }  
  39.     return keySet;  
  40. }  
  41.  
  42. public Collection<V> values() {  
  43.     if (values == null) {  
  44.         values = new AbstractCollection<V>() {  
  45.             public Iterator<V> iterator() {  
  46.                 return new Iterator<V>() {  
  47.                     private Iterator<Entry<K,V>> i = entrySet().iterator();  
  48.  
  49.                     public boolean hasNext() {  
  50.                         return i.hasNext();  
  51.                     }  
  52.  
  53.                     public V next() {  
  54.                         return i.next().getValue();//!!! 
  55.                     }  
  56.  
  57.                     public void remove() {  
  58.                         i.remove();  
  59.                     }  
  60.                 };  
  61.             }  
  62.  
  63.             public int size() {  
  64.                 return AbstractMap.this.size();  
  65.             }  
  66.  
  67.             public boolean isEmpty() {  
  68.                 return AbstractMap.this.isEmpty();  
  69.             }  
  70.  
  71.             public void clear() {  
  72.                 AbstractMap.this.clear();  
  73.             }  
  74.  
  75.             public boolean contains(Object v) {  
  76.                 return AbstractMap.this.containsValue(v);  
  77.             }  
  78.         };  
  79.     }  
  80.     return values;  
[java] view plaincopyprint?
  1. public Set<K> keySet() { 
  2.     if (keySet == null) { 
  3.         keySet = new AbstractSet<K>() { 
  4.             public Iterator<K> iterator() { 
  5.                 return new Iterator<K>() { 
  6.                     private Iterator<Entry<K,V>> i = entrySet().iterator(); 
  7.  
  8.                     public boolean hasNext() { 
  9.                         return i.hasNext(); 
  10.                     } 
  11.  
  12.                     public K next() { 
  13.                         return i.next().getKey();//!!! 
  14.                     } 
  15.  
  16.                     public void remove() { 
  17.                         i.remove(); 
  18.                     } 
  19.                 }; 
  20.             } 
  21.  
  22.             public int size() { 
  23.                 return AbstractMap.this.size(); 
  24.             } 
  25.  
  26.             public boolean isEmpty() { 
  27.                 return AbstractMap.this.isEmpty(); 
  28.             } 
  29.  
  30.             public void clear() { 
  31.                 AbstractMap.this.clear(); 
  32.             } 
  33.  
  34.             public boolean contains(Object k) { 
  35.                 return AbstractMap.this.containsKey(k); 
  36.             } 
  37.         }; 
  38.     } 
  39.     return keySet; 
  40.  
  41. public Collection<V> values() { 
  42.     if (values == null) { 
  43.         values = new AbstractCollection<V>() { 
  44.             public Iterator<V> iterator() { 
  45.                 return new Iterator<V>() { 
  46.                     private Iterator<Entry<K,V>> i = entrySet().iterator(); 
  47.  
  48.                     publicboolean hasNext() { 
  49.                         return i.hasNext(); 
  50.                     } 
  51.  
  52.                     public V next() { 
  53.                         return i.next().getValue();//!!! 
  54.                     } 
  55.  
  56.                     publicvoid remove() { 
  57.                         i.remove(); 
  58.                     } 
  59.                 }; 
  60.             } 
  61.  
  62.             public int size() { 
  63.                 return AbstractMap.this.size(); 
  64.             } 
  65.  
  66.             public boolean isEmpty() { 
  67.                 return AbstractMap.this.isEmpty(); 
  68.             } 
  69.  
  70.             public void clear() { 
  71.                 AbstractMap.this.clear(); 
  72.             } 
  73.  
  74.             public boolean contains(Object v) { 
  75.                 return AbstractMap.this.containsValue(v); 
  76.             } 
  77.         }; 
  78.     } 
  79.     return values; 
0 0
原创粉丝点击