遍历map的四种方法

遍历map的四种方法 Map.entrySet()这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value),而Set<Map.Entry<K,V>>表示一个映射项的Set。Map.Entry里有相应的getKey和getValue方法,即JavaBean,让我们能够从一个项中取出…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

 Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项(里面有Key和Value),而Set<Map.Entry<K,V>>表示一个映射项的Set。Map.Entry里有相应的getKey和getValue方法,即JavaBean,让我们能够从一个项中取出Key和Value。

 

下面是遍历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");
  
  //第一种:普遍使用,二次取值
  System.out.println("通过Map.keySet遍历key和value:");
  for (String key : map.keySet()) {
   System.out.println("key= "+ key + " and value= " + map.get(key));
  }
  
  //第二种
  System.out.println("通过Map.entrySet使用iterator遍历key和value:");
  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());
  }
  
  //第三种:推荐,尤其是容量大时
  System.out.println("通过Map.entrySet遍历key和value");
  for (Map.Entry<String, String> entry : map.entrySet()) {
   System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
  }
 
  //第四种
  System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
  for (String v : map.values()) {
   System.out.println("value= " + v);
  }
 }

下面是HashMap的源代码:

首先HashMap的底层实现用的时候一个Entry数组


   
   
   
  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; //声明了一个数组
  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]; //初始化数组的大小为DEFAULT_INITIAL_CAPACITY(这里是16)
  11. init();
  12. }</pre><br>

再来看一下Entry是在什么地方定义的,继续上源码,我们在HashMap的源码的674行发现了它的定义,原来他是HashMap的一个内部类,并且实现了Map.Entry接口,以下有些地方是转载安静

 


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

 

既然这样那我们再看一下Map.Entry这个接口是怎么定义的,原来他是Map的一个内部接口并且定义了一些方法​​​​​​​


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

 

     看到这里的时候大伙儿估计都明白得差不多了为什么HashMap为什么要选择Entry数组来存放key-value对了吧,因为Entry实现的Map.Entry接口里面定义了getKey(),getValue(),setKey(),setValue()等方法相当于一个javaBean,对键值对进行了一个封装便于后面的操作,从这里我们其实也可以联想到不光是HashMap,譬如LinkedHashMap,TreeMap 等继承自map的容器存储key-value对都应该使用的是Entry只不过组织Entry的形式不一样,HashMap用的是数组加链表的形式,LinkedHashMap用的是链表的形式,TreeMap应该使用的二叉树的形式,不信的话上源码

 

LinkedHashMap:​​​​​​​


  1. /**
  2. * The head of the doubly linked list.
  3. */
  4. /定义了链头
  5. private transient Entry<K,V> header;

 

初始化链表的方法:


  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. //定义根节点
  3. private transient Entry<K,V> root = null;

​​​​​​​

再看他的put方法,是不是很面熟(二叉排序树的插入操作)​​​​​​​


  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,明白了各种Map的底层存储key-value对的方式后,再来看看如何遍历map吧,这里用HashMap来演示吧

 

 Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。

so,很容易写出如下的遍历代码​​​​​​​


  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. 另外,还有一种遍历方法是,单纯的遍历value值,Map有一个values方法,返回的是value的Collection集合。通过遍历collection也可以遍历value,如
  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();

 

原文转至:https://blog.csdn.net/kyi_zhu123/article/details/52769469

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190964.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号