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. 使用git同步代码

    方法1.先把远程仓库clone到本地,本地修改后再push到gitee的远程仓库 1. 配置本地的git配置信息 git config -l #查看git本地配置信息 # 如果没有配置,需要配置自己的 ...

  2. js 前端词典对象的属性和值读取

    通常服务端返回比较奇葩的数据对象,不知道该怎么将这个对象转换为可用实体,想了很久,突发奇想想到了这么个方法. 需求是这样:企业有多个产品,产品有分为很几个种类.服务端有获取产品的接口,和单独获取产品种 ...

  3. 关于MongoDB的简单理解(二)--Java篇

    一.声明 本文依赖于 MongoDB JVM DRIVERS 4.1 版本编写. 本文案例依赖于 Maven 项目管理工具. 二.本文主要讲解哪些内容? 如何连接到MongoDB 通过TLS/SSL连 ...

  4. 同时执行多个$.getJSON() 出现数据混乱的问题的解决

    $.getJSON() $.getJSON( url [, data ] [, success(data, textStatus, jqXHR) ] ) url是必选参数,表示json数据的地址: d ...

  5. 将Oracle数据,以及表结构如何传输至MySQL

    最近研究数据库,将Oracle数据库中的表结构以及数据传输给MySQL数据库,自己通过学习采用两种方式,效率较高. 方式一:Navicat 自从下载了Navicat,真的发现这是一款操作数据库十分优秀 ...

  6. linux下mysql基于mycat做主从复制和读写分离之基础篇

    Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , my ...

  7. Spring Boot:定时任务与图片压缩处理

    一.定时任务 1.创建定时任务 2.@Scheduled 二.图片压缩处理 1.添加thumbnailator依赖 2.创建图片处理类 3.基本使用方法 一.定时任务 项目中可以采用定时任务进行一些操 ...

  8. telnet | ping

    ping通常是用来检查网络是否通畅或者网络连接速度的命令.  ping www.baidu.com 而telnet是用来探测指定ip是否开放指定端口的. telnet xxx 443 查看443开放没 ...

  9. vmware安装linux系统,自动建立没选项

    虚拟机安装CentOS自己跳过分区,直接就到最后的软件包安装了 建完系统后不用power on,建完后在edit一下系统参数,应该会看见两个cd, 有一个是vmware自己加的,把那个删除后在开机就可 ...

  10. Linux常用命令详解(第一章)(ls、man、pwd、cd、mkdir、echo、touch、cp、mv、rm、rmdir、)

    本章命令(共11个): 1 2 3 4 5 6 ls man pwd cd mkdir echo touch cp mv rm rmdir 1. " ls " 作用:列出指定目录下 ...