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的四种方法:

 1 public static void main(String[] args) {
2
3
4 Map<String, String> map = new HashMap<String, String>();
5 map.put("1", "value1");
6 map.put("2", "value2");
7 map.put("3", "value3");
8
9 //第一种:普遍使用,二次取值
10 System.out.println("通过Map.keySet遍历key和value:");
11 for (String key : map.keySet()) {
12 System.out.println("key= "+ key + " and value= " + map.get(key));
13 }
14
15 //第二种
16 System.out.println("通过Map.entrySet使用iterator遍历key和value:");
17 Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
18 while (it.hasNext()) {
19 Map.Entry<String, String> entry = it.next();
20 System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
21 }
22
23 //第三种:推荐,尤其是容量大时
24 System.out.println("通过Map.entrySet遍历key和value");
25 for (Map.Entry<String, String> entry : map.entrySet()) {
26 System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
27 }
28
29 //第四种
30 System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
31 for (String v : map.values()) {
32 System.out.println("value= " + v);
33 }
34 }

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

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

  回归前传,为什么HashMap为什么要选择Entry数组来存放key-value?

  因为Entry实现的Map.Entry接口里面定义了getKey(),getValue(),setKey(),setValue()等方法相当于一个javaBean,对键值对进行了一个封装便于后面的操作,从这里我们其实也可以联想到不光是HashMap,譬如LinkedHashMap,TreeMap 等继承自map的容器存储key-value对都应该使用的是Entry只不过组织Entry的形式不一样,HashMap用的是数组加链表的形式,LinkedHashMap用的是链表的形式,TreeMap应该使用的二叉树的形式。

  keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。

  所以,遍历HashMap一共有开头的四种方法,也不难理解为什么有了keySet(),values(),iterator()还要再使用Entry。

Over...

参考:

  1. https://blog.csdn.net/yaomingyang/article/details/78748130
  2. https://blog.csdn.net/kyi_zhu123/article/details/52769469

关于HashMap遍历,为什么要用entry的更多相关文章

  1. Java中HashMap遍历的两种方式

    Java中HashMap遍历的两种方式 转]Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml 第一种: ...

  2. HashMap遍历

    package com.jackey.topic; import java.util.ArrayList;import java.util.HashMap;import java.util.Itera ...

  3. [Java] HashMap遍历的两种方式

    Java中HashMap遍历的两种方式原文地址: http://www.javaweb.cc/language/java/032291.shtml第一种: Map map = new HashMap( ...

  4. HashMap遍历,推荐使用entrySet()

    之前map遍历,偶尔会先去keyset然后再遍历keyset 比如 Map map = new HashMap(); Iterator it = map.keySet().iterator(); wh ...

  5. HashMap 遍历的两种方式及性能比较

    HashMap 是Java开发中经常使用的数据结构.相信HashMap 的基本用法你已经很熟悉了.那么我们该如何遍历HashMap 呢?哪种遍历方式的性能更好呢?本篇文章来为你解决这个疑惑. 一.Ha ...

  6. java 中 HashMap 遍历与删除

    HashMap的遍历 方法一.这是最常见的并且在大多数情况下也是最可取的遍历方式 /** * 在键值都需要时使用 */ Map<Integer, Integer> map = new Ha ...

  7. 史上最全HashMap遍历方式

    java Hashmap Map TreeMap 的几种遍历方式,全网最全,全网最强 package Collec2; import java.util.HashMap; import java.ut ...

  8. HashMap遍历的两种方式

    第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) {    ...

  9. HashMap遍历方式探究

    HashMap的遍历有两种常用的方法,那就是使用keyset及entryset来进行遍历,但两者的遍历速度是有差别的,下面请看实例: package com.HashMap.Test; import ...

随机推荐

  1. k8s之共享存储概述以及演示

    共享存储机制 k8s对有状态的容器应用或者需要对数据进行持久化的应用,在之前的篇章说过,可以将容器内的目录挂载到宿主机的容器目录或者emptyDir临时存储卷. 另外,k8s还开放了两个资源,分别是P ...

  2. 使用Python对MySQL数据库插入二十万条数据

    1.当我们测试的时候需要大量的数据的时候,往往需要我们自己造数据,一条一条的加是不现实的,这时候就需要使用脚本来批量生成数据了. import pymysql import random import ...

  3. notepad文件对比

    一/格式转换 我用的是json,就以这个为例吧: 打开软件--插件--插件管理 搜索着两个进行安装,自动重启打开 将文件的代码做好,选择语言--J--可以找到json 用刚安装的插件--json vi ...

  4. 网络优化之net.ipv4.tcp_tw_recycle和tcp_tw_reuse参数

    网络优化之net.ipv4.tcp_tw_recycle和tcp_tw_reuse参数 - 一个人默默潜行 - 博客园 https://www.cnblogs.com/ppp1314520818/p/ ...

  5. innodb和myisam原理

    MyISAM索引实现 MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址.如图:  这里设表一共有三列,假设我们以Col1为主键,则上图是一个MyISAM表的主索引 ...

  6. LOJ10104Blockade

    POI 2008 Byteotia 城市有 n 个城镇,m 条双向道路.每条道路连接两个不同的城镇,没有重复的道路,所有城镇连通.输出 n 个数,代表如果把第i  个点去掉,将有多少对点不能互通. 输 ...

  7. LOJ10128. 花神游历各国

    花神喜欢步行游历各国,顺便虐爆各地竞赛.花神有一条游览路线,它是线型的,也就是说,所有游历国家呈一条线的形状排列,花神对每个国家都有一个喜欢程度(当然花神并不一定喜欢所有国家). 每一次旅行中,花神会 ...

  8. Spark练习之wordcount,基于排序机制的wordcount

    Spark练习之wordcount 一.原理及其剖析 二.pom.xml 三.使用Java进行spark的wordcount练习 四.使用scala进行spark的wordcount练习 五.基于排序 ...

  9. Linux系统安装时分区的选择(转)

    原文地址:http://www.cnblogs.com/gylei/archive/2011/12/04/2275987.html 前言: 以前初识Linux时,对Linux系统安装时分区的选择,一点 ...

  10. 6. Linux输入输出重定向

    1.输入重定向是指把文件导入到命令中,而输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中. 输入重定向中用到的符号及其作用 输出重定向中用到的符号及其作用 1)通过输出重定向将原本要输出到 ...