遍历map的四种方法

article/2025/9/10 12:53:31

 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


http://chatgpt.dhexx.cn/article/xgxxfho8.shtml

相关文章

遍历Map的六种方式

遍历Map的六种方式 一.创建Map二.遍历Map方式一&#xff1a;使用entrySet遍历(推荐使用)方式二&#xff1a;使用keySet遍历方式三&#xff1a;使用entrySetIterator遍历方式四&#xff1a;使用keySetIterator遍历方式五&#xff1a;使用keySet、values方法遍历方式六&#xff1…

Map.entry详解

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

遍历map的几种方法

#先往map加入几个数据 Map<Integer,String> mapnew HashMap<>();map.put(1,"美好的周一");map.put(2,"美好的周二");map.put(3,"美好的周三");方法一&#xff1a;普通的foreach循环&#xff0c;使用keySet()方法&#xff0c;遍历key…

The operator ‘SUBTRACT‘ is not supported between objects of type ‘null‘ and ‘java.lang.Integer‘

找了半天发现是判断id值是否为空时&#xff0c;数据类型发生转换问题。关于Integer和int在面试的时候出现的频率很高。而我们所熟知的是Integer是int 的包装类型&#xff0c;int的初始值为0&#xff0c;Integer的初始值为null。 org.springframework.expression.spel.SpelEvalu…

Spark Transformation —— subtract

上手使用 def subtract(other: RDD[T]): RDD[T] def subtract(other: RDD[T], numPartitions: Int): RDD[T] def subtract(other: RDD[T], partitioner: Partitioner)(implicit ord: Ordering[T] null): RDD[T] 该函数类似于intersection&#xff0c;但返回在RDD中出现&…

java 中subtract_Java.math.BigDecimal.subtract()方法实例

全屏 Java.math.BigDecimal.subtract()方法实例 java.math.BigDecimal.subtract(BigDecimal subtrahend)返回一个BigDecimal&#xff0c;其值为 (this - subtrahend), 精度为 max(this.scale(), subtrahend.scale()). 声明 以下是声明java.math.BigDecimal.subtract()方法publi…

bedtools subtract 基因区段取差集

基本概述&#xff1a; bedtools subtract 通俗的说&#xff0c;得到 A - B 的区段。如果在A中发现了B区段&#xff0c;就把 B 扣除&#xff0c;通过不同的参数&#xff0c;扣除的标准不一样。其中&#xff0c;参数 -A 可以达成 Remove features with any overlap 的效果&#x…

cv::subtract

计算两个数组或数组和标量之间的每个元素差。也就是图像的相减操作 opencv documentation的说明&#xff1a; 参数说明&#xff1a; src1:第一个输入数组或标量。 src2:第二个输入数组或标量。 src3:输出数组与输入数组有相同的大小和相同数量的通道。 src4:可选操作掩码;…

opencv之subtract

函数原型 void cv::subtract(InputArray src1, InputArray src2, OutputArray dst, InputArray masknoArray(), int dtype-1) python: dst cv.subtract(src1,src2[,dst[,mask[,dtype]]]) 参数说明 src1:input array or scalar src2:input array or scalar dst:output array…

OpenCV函数subtract()使用心得及需要注意的地方

OpenCV函数subtract()的原型如下&#xff1a; void cv::subtract( InputArray src1,InputArray src2,OutputArray dst,InputArray mask noArray(),int dtype -1 ) 官方文档说明如下&#xff1a; 看了以上文档并结合自己的使用&#xff0c;补充说明以下几点&#xff1a;…

moment系列一:add() 方法和subtract() 方法的使用

在工作中&#xff0c;因为自己去搜博客的时候老是找不到自己想要的答案&#xff0c;甚至一篇博客下来&#xff0c;找了好久都没收获&#xff0c;倍感疲惫&#xff0c;所以这里就废话不多说&#xff0c;直接上内容吧。 moment 中文官网地址&#xff1a;http://momentjs.cn momen…

基于改进EAST算法的文本检测

这段时间阅读研究了EAST算法以及在EAST算法上的改进并完成了复现运用到其他场景中去。 当今社会已进入图像大数据时代&#xff0c;图像数量庞大种类繁多&#xff0c;包含大量的有用知识。从图像中高效、精准、全面地提取文本和地理信息坐标等有用知识这一课题&#xff0c;也成…

自然文本检测主要模型

自然文本检测主要模型 CTPN模型 CTPN是目前流传最广、影响最大的开源文本检测模型&#xff0c;可以检测水平或微斜的文本行。文本行可以被看成一个字符sequence&#xff0c;而不是一般物体检测中单个独立的目标。同一文本行上各个字符图像间可以互为上下文&#xff0c;在训练…

深度学习:多场景多尺度的文本检测

《Fused Text Segmentation Networks for Multi-oriented Scene Text Detection》 用于多场景文本检测的融合文本分割网络。&#xff08;2018.5.7&#xff09; 文章笔记 摘要 - 本文从实例感知语义分割的角度介绍了一种新的面向多向场景文本检测的端到端框架。 我们提出了融…

FOTS:自然场景的文本检测与识别

在这篇文章里&#xff0c;我将分享我实现这篇论文的方法。 问题描述数据集关于数据使用的损失函数准备检测数据准备识别数据训练检测模型和识别模型代码整合显示结果引用 问题描述 我们需要从任何图像(包含文本)检测文本区域&#xff0c;这个图像可以是任何具有不同背景的东…

【文本检测】DBNet

目录 论文正文概述细节整体流程二值化自适应的门限可变形卷积标注损失计算推理 感悟 论文正文 链接&#xff1a;链接&#xff0c;提取码&#xff1a;7fmj 概述 文本检测主流的两个方法就是基于回归的方法和基于分割的方法。 基于回归的方法指的是迁移一些经典的目标检测算法…

openCV实践项目:图片文本检测

上一期我们通过对实验&#xff1a;银行卡卡号识别 加深了对前面所学openCV图像处理的一些理解 openCV实践项目&#xff1a;银行卡卡号识别_老师我作业忘带了的博客-CSDN博客 本次图片文本检测相对于要容易一些&#xff0c;内容如下&#xff1a; 一、流程说明 把一个这样的图片…

TextSnake文本检测

论文《TextSnake: A Flexible Representation for Detecting Text of Arbitrary Shapes》 (1) 数据集 文章中提到了4个数据集&#xff1a; 1) Total-Text&#xff1b;(新开源曲线文本数据集) 2) SCUT-CTW1500; (新开源曲线文本数据集) 3) ICDAR 2015;(经典数据集) 4) MSRA…

值得一看的文本检测方法

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 前 言 目前深度学习方法做文本检测比较普遍&#xff0c;但是也存在一些时候GPU资源不够&#xff0c;这时候就需要一些其他的方法来检测文本信息&#xff0c;本文主要介…