zoukankan      html  css  js  c++  java
  • 元组和集合

    在 Scala 创建一个元组类型非常的简单,这只是主体的一部分:如果首先将元素公开给外部,那么在类型内部创建描述这些元素的名称就毫无价值。考虑清单 3:

    清单 3. tuples.scala

     // JUnit test suite  
        //  
        class TupleTest  
        {  
          import org.junit._, Assert._  
          import java.util.Date  
           
          @Test def simpleTuples() =  
          {  
            val tedsStartingDateWithScala = Date.parse("3/7/2006")  
         
            val tuple = ("Ted", "Scala", tedsStartingDateWithScala)  
              
            assertEquals(tuple._1, "Ted")  
            assertEquals(tuple._2, "Scala")  
            assertEquals(tuple._3, tedsStartingDateWithScala)  
          }  
        } 

    创建元组非常简单,将值放入一组圆括号内,就好象调用一个方法调用一样。提取这些值只需要调用 “_n” 方法,其中 n 表示相关的元组元素的位置参数:_1 表示第一位,_2 表示第二位,依此类推。传统的 Java java.util.Map 实质上是一个分两部分的元组集合。

    元组可以轻松地实现使用单个实体移动多个值,这意味着元组可以提供在 Java 编程中非常重量级的操作:多个返回值。例如,某个方法可以计算 String 中字符的数量,并返回该 String 中出现次数最多的字符,但是如果程序员希望同时 返回最常出现的字符和 它出现的次数,那么程序设计就有点复杂了:或是创建一个包含字符及其出现次数的显式类,或将值作为字段保存到对象中并在需要时返回字段值。无论使用哪种方 法,与使用 Scala 相比,都需要编写大量代码;通过简单地返回包含字符及其出现次数的元组,Scala 不仅可以轻松地使用 “_1”、“_2” 等访问元组的各个值,还可以轻松地返回多个返回值。

    如下节所示,Scala 频繁地将 Option 和元组保存到集合(例如 Array[T] 或列表)中,从而通过一个比较简单的结构提供了极大的灵活性和威力。

    创建元组非常简单,将值放入一组圆括号内,就好象调用一个方法调用一样。提取这些值只需要调用 “_n” 方法,其中 n 表示相关的元组元素的位置参数:_1 表示第一位,_2 表示第二位,依此类推。传统的 Java java.util.Map 实质上是一个分两部分的元组集合。

    元组可以轻松地实现使用单个实体移动多个值,这意味着元组可以提供在 Java 编程中非常重量级的操作:多个返回值。例如,某个方法可以计算 String 中字符的数量,并返回该 String 中出现次数最多的字符,但是如果程序员希望同时 返回最常出现的字符和 它出现的次数,那么程序设计就有点复杂了:或是创建一个包含字符及其出现次数的显式类,或将值作为字段保存到对象中并在需要时返回字段值。无论使用哪种方 法,与使用 Scala 相比,都需要编写大量代码;通过简单地返回包含字符及其出现次数的元组,Scala 不仅可以轻松地使用 “_1”、“_2” 等访问元组的各个值,还可以轻松地返回多个返回值。

    如下节所示,Scala 频繁地将 Option 和元组保存到集合(例如 Array[T] 或列表)中,从而通过一个比较简单的结构提供了极大的灵活性和威力。

    数组带

          object ArrayExample1  
        {  
          def main(args : Array[String]) : Unit =  
          {  
            for (i <- 0 to args.length-1)  
            {  
              System.out.println(args(i))  
            }  
          }  
        } 

    您走出阴霾

    让我们重新审视一个老朋友 — 数组 — 在 Scala 中是 Array[T]。和 Java 代码中的数组一样,Scala 的 Array[T] 是一组有序的元素序列,使用表示数组位置的数值进行索引,并且该值不可以超过数组的总大小,如清单 4 所示:

    尽管等同于 Java 代码中的数组(毕竟后者是最终的编译结果),Scala 中的数组使用了截然不同的定义。对于新手,Scala 中的数组实际上就是泛型类,没有增加 “内置” 状态(至少,不会比 Scala 库附带的其他类多)。例如,在 Scala 中,数组一般定义为 Array[T] 的实例,这个类定义了一些额外的有趣方法,包括常见的 “length” 方法,它将返回数组的长度。因此,在 Scala 中,可以按照传统意义使用 Array,例如使用 Int 在 0 到 args.length - 1 间进行迭代,并获取数组的第 i 个元素(使用圆括号而不是方括号来指定返回哪个元素,这是另一种名称比较有趣的方法)。 

    扩展数组

    事实证明 Array 拥有大量方法,这些方法继承自一个非常庞大的 parent 层次结构:Array 扩展 Array0,后者扩展 ArrayLike[A],ArrayLike[A] 扩展 Mutable[A],Mutable[A] 又扩展 RandomAccessSeq[A],RandomAccessSeq[A] 扩展了 Seq[A],等等。实际上,这种层次结构意味着 Array 可以执行很多操作,因此与 Java 编程相比,在 Scala 中可以更轻松地使用数组。

    例如,如清单 4 所示,使用 foreach 方法遍历数组更加简单并且更贴近函数的方式,这些都继承自 Iterable 特性:

      object   
        {  
          def main(args : Array[String]) : Unit =  
          {  
            args.foreach( (arg) => System.out.println(arg) )  
          }  
        } 

    看上去您没有节省多少工作,但是,将一个函数(匿名或其他)传入到另一个类中以便获得在特定语义下(在本例中指遍历数组)执行的能力,是函数编程的 常见主题。以这种方式使用更高阶函数并不局限于迭代;事实上,还得经常对数组内容执行一些过滤 操作去掉无用的内容,然后再处理结果。例如,在 Scala 中,可以轻松地使用 filter 方法进行过滤,然后获取结果列表并使用 map 和另一个函数(类型为 (T) => U,其中 T 和 U 都是泛型类型),或 foreach 来处理每个元素。我在清单 6 中采取了后一种方法(注意 filter 使用了一个 (T) : Boolean 方法,意味着使用数组持有的任意类型的参数,并返回一个 Boolean)。

    清单 6. 查找所有 Scala 程序员

     class ArrayTest  
        {  
          import org.junit._, Assert._  
            
          @Test def testFilter =  
          {  
            val programmers = Array(  
                new Person("Ted", "Neward", 37, 50000,  
                  Array("C++", "Java", "Scala", "Groovy", "C#", "F#", "Ruby")),  
                new Person("Amanda", "Laucher", 27, 45000,  
                  Array("C#", "F#", "Java", "Scala")),  
                new Person("Luke", "Hoban", 32, 45000,  
                  Array("C#", "Visual Basic", "F#")),  
          new Person("Scott", "Davis", 40, 50000,  
            Array("Java", "Groovy"))  
              )  
         
            // 查找所有Scala程序员 ...  
            val scalaProgs =  
              programmers.filter((p) => p.skills.contains("Scala") )  
              
            // 应该只有2  
            assertEquals(2, scalaProgs.length)  
              
            // ... now perform an operation on each programmer in the resulting  
            // array of Scala programmers (give them a raise, of course!)  
            //  
            scalaProgs.foreach((p) => p.salary += 5000)  
              
            // Should each be increased by 5000 ...  
            assertEquals(programmers(0).salary, 50000 + 5000)  
            assertEquals(programmers(1).salary, 45000 + 5000)  
              
            // ... except for our programmers who don't know Scala  
            assertEquals(programmers(2).salary, 45000)  
         assertEquals(programmers(3).salary, 50000)  
          }  
        }  

    创建一个新的 Array 时将用到 map 函数,保持原始的数组内容不变,实际上大多数函数性程序员都喜欢这种方式:

    清单 7. Filter 和 map

     @Test def testFilterAndMap =  
        {  
          val programmers = Array(  
              new Person("Ted", "Neward", 37, 50000,  
                Array("C++", "Java", "Scala", "C#", "F#", "Ruby")),  
              new Person("Amanda", "Laucher", 27, 45000,  
                Array("C#", "F#", "Java", "Scala")),  
              new Person("Luke", "Hoban", 32, 45000,  
                Array("C#", "Visual Basic", "F#"))  
        new Person("Scott", "Davis", 40, 50000,  
          Array("Java", "Groovy"))  
            )  
         
          // Find all the Scala programmers ...  
          val scalaProgs =  
            programmers.filter((p) => p.skills.contains("Scala") )  
            
          // Should only be 2  
          assertEquals(2, scalaProgs.length)  
            
          // ... now perform an operation on each programmer in the resulting  
          // array of Scala programmers (give them a raise, of course!)  
          //  
          def raiseTheScalaProgrammer(p : Person) =  
          {  
            new Person(p.firstName, p.lastName, p.age,  
              p.salary + 5000, p.skills)  
          }  
          val raisedScalaProgs =   
            scalaProgs.map(raiseTheScalaProgrammer)  
            
          assertEquals(2, raisedScalaProgs.length)  
          assertEquals(50000 + 5000, raisedScalaProgs(0).salary)  
          assertEquals(45000 + 5000, raisedScalaProgs(1).salary)  
        }  

    注意,在清单 7 中,Person 的 salary 成员可以标记为 “val”,表示不可修改,而不是像上文一样为了修改不同程序员的薪资而标记为 “var”。

    Scala 的 Array 提供了很多方法,在这里无法一一列出并演示。总的来说,在使用数组时,应该充分地利用 Array 提供的方法,而不是使用传统的 for ... 模式遍历数组并查找或执行需要的操作。最简单的实现方法通常是编写一个函数(如果有必要的话可以使用嵌套,如清单 7 中的 testFilterAndMap 示例所示),这个函数可以执行所需的操作,然后根据期望的结果将该函数传递给 Array 中的 map、filter、foreach 或其他方法之一。

  • 相关阅读:
    git相关指令
    深刻理解回调函数
    将本地项目托管到GitHub、码云、GitLab的步骤
    各种安装依赖、插件、创建项目的指令
    IOS MBProgressHUD的使用
    2012武汉华为机试题
    GTK+2 多线程模型
    bindtextdomain()/textdomain() 设置文本域目录及文本域文件
    在Linux下开发多语言软件: Hello GetText!
    转:getaddrinfo函数详解
  • 原文地址:https://www.cnblogs.com/rxingyue/p/4146531.html
Copyright © 2011-2022 走看看