Groovy - 闭包

  • 简述

    闭包是一个简短的匿名代码块。它通常只跨越几行代码。方法甚至可以将代码块作为参数。他们本质上是匿名的。
    以下是一个简单闭包的示例及其外观。
    
    class Example {
       static void main(String[] args) {
          def clos = {println "Hello World"};
          clos.call();
       } 
    }
    
    在上面的示例中,代码行 - {println "Hello World"} 被称为闭包。这个标识符引用的代码块可以用调用语句来执行。
    当我们运行上面的程序时,我们将得到以下结果 -
    
    Hello World
    
  • 闭包中的形式参数

    闭包还可以包含形式参数,以使其更有用,就像 Groovy 中的方法一样。
    
    class Example {
       static void main(String[] args) {
          def clos = {param->println "Hello ${param}"};
          clos.call("World");
       } 
    }
    
    在上面的代码示例中,请注意 ${param} 的使用,它导致闭包采用参数。当通过 clos.call 语句调用闭包时,我们现在可以选择将参数传递给闭包。
    当我们运行上面的程序时,我们将得到以下结果 -
    
    Hello World
    
    下图重复前面的示例并产生相同的结果,但显示可以使用称为 it 的隐式单个参数。这里的“it”是 Groovy 中的关键字。
    
    class Example {
       static void main(String[] args) {
          def clos = {println "Hello ${it}"};
          clos.call("World");
       } 
    }
    
    当我们运行上面的程序时,我们将得到以下结果 -
    
    Hello World
    
  • 闭包和变量

    更正式地说,闭包可以在定义闭包时引用变量。以下是如何实现这一目标的示例。
    
    class Example {     
       static void main(String[] args) {
          def str1 = "Hello";
          def clos = {param -> println "${str1} ${param}"}
          clos.call("World");
          
          // We are now changing the value of the String str1 which is referenced in the closure
          str1 = "Welcome";
          clos.call("World");
       } 
    }
    
    在上面的示例中,除了向闭包传递参数外,我们还定义了一个名为 str1 的变量。闭包还接受变量和参数。
    当我们运行上面的程序时,我们将得到以下结果 -
    
    Hello World 
    Welcome World
    
  • 在方法中使用闭包

    闭包也可以用作方法的参数。在 Groovy 中,许多用于数据类型(例如列表和集合)的内置方法都将闭包作为参数类型。
    以下示例显示了如何将闭包作为参数发送到方法。
    
    class Example { 
       def static Display(clo) {
          // This time the $param parameter gets replaced by the string "Inner"         
          clo.call("Inner");
       } 
       
       static void main(String[] args) {
          def str1 = "Hello";
          def clos = { param -> println "${str1} ${param}" }
          clos.call("World");
          
          // We are now changing the value of the String str1 which is referenced in the closure
          str1 = "Welcome";
          clos.call("World");
          
          // Passing our closure to a method
          Example.Display(clos);
       } 
    }
    
    在上面的例子中,
    • 我们正在定义一个名为 Display 的静态方法,它接受一个闭包作为参数。
    • 然后我们在 main 方法中定义一个闭包,并将其作为参数传递给 Display 方法。
    当我们运行上面的程序时,我们将得到以下结果 -
    
    Hello World 
    Welcome World 
    Welcome Inner
    
  • 集合和字符串中的闭包

    多个 List、Map 和 String 方法接受闭包作为参数。让我们看一下如何在这些数据类型中使用闭包的示例。

    对列表使用闭包

    以下示例显示了如何将闭包与列表一起使用。在下面的示例中,我们首先定义一个简单的值列表。然后,列表集合类型定义了一个名为 的函数。每个。此函数将闭包作为参数并将闭包应用于列表的每个元素。
    
    class Example {
       static void main(String[] args) {
          def lst = [11, 12, 13, 14];
          lst.each {println it}
       } 
    }
    
    当我们运行上面的程序时,我们将得到以下结果 -
    
    11 
    12 
    13 
    14
    

    将闭包与地图一起使用

    以下示例显示如何将闭包与地图一起使用。在下面的示例中,我们首先定义一个简单的键值项映射。然后,地图集合类型定义了一个名为 .each 的函数。此函数将闭包作为参数并将闭包应用于映射的每个键值对。
    
    class Example {
       static void main(String[] args) {
          def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]             
          mp.each {println it}
          mp.each {println "${it.key} maps to: ${it.value}"}
       } 
    }
    
    当我们运行上面的程序时,我们将得到以下结果 -
    
    TopicName = Maps 
    TopicDescription = Methods in Maps 
    TopicName maps to: Maps 
    TopicDescription maps to: Methods in Maps
    
    通常,我们可能希望遍历集合的成员并仅在元素满足某些条件时才应用某些逻辑。这很容易用闭包中的条件语句处理。
    
    class Example {
       static void main(String[] args) {
          def lst = [1,2,3,4];
          lst.each {println it}
          println("The list will only display those numbers which are divisible by 2")
          lst.each{num -> if(num % 2 == 0) println num}
       } 
    }
    
    上面的示例显示了在闭包中使用的条件 if(num % 2 == 0) 表达式,用于检查列表中的每个项目是否可以被 2 整除。
    当我们运行上面的程序时,我们将得到以下结果 -
    
    1 
    2 
    3 
    4 
    The list will only display those numbers which are divisible by 2.
    2 
    4 
    
  • 与闭包一起使用的方法

    闭包本身提供了一些方法。
    序号 方法与说明
    1 find()
    find 方法在集合中找到第一个符合某些条件的值。
    2 findAll()
    它在接收对象中找到与关闭条件匹配的所有值。
    3 any() & every()
    方法 any 遍历集合的每个元素,检查布尔谓词是否对至少一个元素有效。
    4 collect()
    collect 方法遍历集合,使用闭包作为转换器将每个元素转换为新值。