技术开发 频道

实战 Groovy: for each 剖析

  Map 迭代

  从前文可以看到,在 Java 语言中,无法直接迭代 Map。在 Groovy 中,这完全不是问题,如清单 8 所示:

  清单 8. Groovy map 迭代  

def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]

  map.each{ println it }

  要处理名称/值对,可以使用隐式的 getKey() 和 getValue() 方法,或在包的开头部分显式地命名变量,如清单 9 所示:

  清单 9. 从 map 获得键和值  

def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]

  map.each{

  println it.key

  println it.value

  }

  map.each{k,v
->

  println k

  println v

  }

  可以看到,迭代 Map 和迭代其它任何集合一样自然。

  在继续研究下一个迭代例子前,应当了解 Groovy 中有关 Map 的另一个语法。与在 Java 语言中调用 map.get("Java") 不一样,可以简化对 map.Java 的调用,如清单 10 所示:

  清单 10. 获得 map 值  

def map = ["Java":"server", "Groovy":"server", "JavaScript":"web"]

  
//identical results

  println map.get(
"Java")

  println map.Java

  不可否认,Groovy 针对 Map 的这种便捷语法非常酷,但这也是在对 Map 使用反射时引起一些常见问题的原因。对 list.class 的调用将生成 java.util.ArrayList,而调用 map.class 返回 null。这是因为获得 map 元素的便捷方法覆盖了实际的 getter 调用。Map 中的元素都不具有 class 键,因此调用实际会返回 null,如清单 11 的示例所示:

  清单 11. Groovy map 和 null  

def list = ["Java", "Groovy", "JavaScript"]

  println list.class

  
// java.util.ArrayList

  def map
= ["Java":"server", "Groovy":"server", "JavaScript":"web"]

  println map.class

  
// null

  map.class
= "I am a map element"

  println map.class

  
// I am a map element

  println map.getClass()

  
// class java.util.LinkedHashMap

  这是 Groovy 比较罕见的打破 “最少意外原则” 的情况,但是由于从 map 获取元素要比使用反射更加常见,因此我可以接受这一例外。

0
相关文章