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. kernel升级模式RKS让人振奋

    前几天刚将我的ERP内核从701_rel 升级到721_ext_rel,看到721的说明了讲到,对于这次的更新,支持RKS(Rolling Kernel Switch)了,简单的讲,就是以后对于内核的 ...

  2. 1V转3V的低功耗升压芯片

       由于1V的电压很低,如果需要1V转3V的芯片,也是能找到的,一般要输入电压要选择余量,选择比1V更低的启动电压的1V转3V升压芯片.PW5100干电池升压IC就具有1V转3V,稳压输出3.3V的 ...

  3. Sentry(v20.12.1) K8S 云原生架构探索,JavaScript Enriching Events(丰富事件信息)

    系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...

  4. linux 文件目录权限

    文件目录权限: 什么是文件权限: 在Linux中,每个文件都有所属的所有者,和所有组,并且规定了文件的所有者,所有组以及其他人对文件的,可读,可写,可执行等权限. 对于目录的权限来说,可读是读取目录文 ...

  5. DDOS攻击方式总结以及免费DDOS攻击测试工具大合集

    若有雷同或者不足之处,欢迎指正交流,谢谢! DoS(Denial Of Service)攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段残忍地耗尽被攻击对象的资源,目的是让目标计算机或网络无法提 ...

  6. Let’s Encrypt/Certbot移除/remove/revoke不需要的域名证书

    1.首先确认你的证书不再需要,如果有必要,请执行下面的命令进行备份 cp /etc/letsencrypt/ /etc/letsencrypt.backup -r 2.撤销证书然后删除证书 [root ...

  7. pycharm安装完成后的一些基本设置

    1.设置背景色 file-->Setting-->Appearance&Behavior-->Appearance 2.设置主题 settings --> editor ...

  8. 慕课网金职位 Python工程师 百度网盘下载

    百度网盘链接:https://pan.baidu.com/s/1xshLRO3ru0LAsQQ0pE67Qg 提取码:bh9f 如果失效加我微信:610060008[视频不加密,资料代码齐全,超清一手 ...

  9. 洛谷 P4999

    题目链接: P4999 烦人的数学作业 题目大意 详见题目 solution 有一个显而易见的结论 发现 \(ans_{l, r} = ans_{1. r} - ans_{1, l - 1}\) 那只 ...

  10. nohup和&后台运行,进程查看及终止

    文章目录 一.nohup 1.1用途:不挂断地运行命令. 1.2语法:nohup Command [ Arg - ] [ & ] 1.3退出状态:该命令返回下列出口值: 二.& 2.1 ...