scala编程练习 - CSDN
精华内容
参与话题
  • 说多不如少练,我们今天就开始练习如何使用Scala编程。 虽然Scala是一门比较新的语言,但是很多机构都为其开发了IDE或者集成插件,比较流行的有Eclipse、IntelliJ以及Netbeans。今天我们使用集成了Scala IDE插件的...

    简介

    在上一篇文章中,我们阐述了Coursera使用Scala的理由,以及Scala的优缺点。说多不如少练,我们今天就开始练习如何使用Scala编程。

    虽然Scala是一门比较新的语言,但是很多机构都为其开发了IDE或者集成插件,比较流行的有Eclipse、IntelliJ以及Netbeans。今天我们使用集成了Scala IDE插件的Eclipse进行代码的编写。


    IDE下载及安装

    我们在Scala IDE的官网可以下载到最新版本的Scala IDE for Eclipse(本文采用3.0.2 Release),有两种下载方式可以选择:Bundle方式以及插件方式。其中前者是将Scala插件集成到Eclipse中的捆绑下载,而后者提供在已有Eclipse IDE上安装Scala插件的选择。你可以根据自己的需求以及系统型号来选择。Bundle安装包中包含了以下内容:

    • Eclipse 4.3.1 (Kepler)
    • Scala IDE 3.0.2
    • Scala Worksheet 0.2.1
    • Play Framework support 0.4.1
    • m2eclipse-scala Maven connector 0.4.3
    • access to the full Scala IDE ecosystem

    Bundle安装包解压后,打开Eclipse IDE,在Help=》Install New Software中可以看到已安装的插件包含了以上列表中的内容:


    如果选择插件方式安装,可以根据上述列表将内容整合到Eclipse中,已达到最好效果。

    注意:无论采用哪种方式安装,确保你的节点上有JDK6 or JDK7。


    创建工程

    安装完毕之后,我们依次File=》New=》New Scala Project,可以新建一个Scala工程,如下图所示:


    点击Next,可以配置一下工程属性,我们可以看到工程的依赖项包含了JDK以及SDK:



    编写代码

    在包中创建Scala代码类,当前我们创建的是一个Scala对象(Object),Scala对象是Scala中类的单例模式,Object标明了在内存中只会存在一个HelloWord实例。



    接下来,我们编写main方法,代码如下:

    package com.doggie
    
    object HelloWorld {
      def main(args: Array[String]): Unit = {
    	  println("hello world")
      }
    
    }

    我们注意到main方法并没有使用static修饰,而Scala中已经摒弃了static作为方法的关键字。mian方法的入参是一个Array[String],即为一个String数组,这与java中一致。但是Scala中使用方括号而不是尖括号来指定泛型的类型。这有效避免了与尖括号作为方法名称(以后的文章中会涉及)的混淆。

    而Scala类中方法的定义形式如下:def 方法名(参数): 返回值类型 = {方法体}

    其中参数和返回值的模式为:val: type,这种变量名在前、变量类型在后、相互之间使用冒号隔开的方式将贯穿在Scala的代码中。另外方法和方法体之间使用等号隔开。

    返回值的类型为Unit,相当于java中的void。

    java中使用print和println方法向控制台输出,地位相当于java中的System.out.print以及System.out.println,实际上通过查阅代码,print和println确实是对System.out中相应方法的调用:

    private val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
    def out = outVar.value
    def println(x: Any) { out.println(x) }
    def println(x: Any) = Console.println(x)

    另外一个细节是,Scala中将约定每行结尾可以不加分号,这恐怕对写习惯了java代码的coder来说有点不习惯(如果同一行包含两条语句,那么必须用分号隔开)。

    如果你观察足够敏锐,当然也会发现Scala连语句缩进也由熟悉的4个空格改为2个空格了。


    结果

    像运行Java代码一样,右键选择Run as Scala Application,在控制台就会见到熟悉的字样了。

    hello world

    其他Scala开发的IDE可以参考:

    http://wiki.netbeans.org/Scala

    http://www.jetbrains.com/idea/


    参考资料:

    http://www.ibm.com/developerworks/cn/java/j-scala01228.html

    http://scala-ide.org/download/sdk.html


    声明:本文为原创,禁止用于任何商业目的,转载请注明出处:http://blog.csdn.net/asongoficeandfire/article/details/21490101

    展开全文
  • 案例练习 求各个城市的平均温度 //需求:求各个城市的平均温度 val d1 = Array(("beijing", 28.1), ("shanghai", 28.7), ("guangzhou", 32.0), (&...

    案例练习
    求各个城市的平均温度

    //需求:求各个城市的平均温度
    val d1 = Array(("beijing", 28.1), ("shanghai", 28.7), ("guangzhou", 32.0), ("shenzhen", 33.1))
    val d2 = Array(("beijing", 27.3), ("shanghai", 30.1), ("guangzhou", 33.3))
    val d3 = Array(("beijing", 28.2), ("shanghai", 29.1), ("guangzhou", 32.0), ("shenzhen", 32.1))
    
    //将城市进行归纳
    val data = d1 ++ d2 ++ d3
    //进行分组
    val groupdata: Map[String, Array[(String, Double)]] = data.groupBy(_._1)
    //求和
    //第一种方法
    val result1 = groupdata.mapValues(arr => {
      val total: (String, Double) = arr.reduce((a, b) => ("", a._2 + b._2))
      val avg = total._2 / arr.length
      avg
    })
    println("result1:" + result1.toList)
    //第二种方法
    //tp代表groupdata
    val result2: Map[String, Double] = groupdata.map(tp => {
      //求总和:首先找到温度,也就是Array里面的Double
      val total: Double = tp._2.map(_._2).sum
      //求月份的个数
      val month: Int = tp._2.size
      (tp._1, total / month)
    })
    println("result2:" + result2.toList)
    //第三种方法
    val result3: Map[String, Double] = groupdata.mapValues(arr => {
      //求总和
      val total: Double = arr.map(_._2).sum
      //月份
      val month: Int = arr.size
      (total / month)
    })
    println("result3:" + result3.toList)
    
    //第四种方法
    val result4 = groupdata.mapValues(arr => {
      val total: Double = arr.foldLeft(0.0)((a, b) => (a + b._2))
      val month: Int = arr.size
      total / month
    })
    println("result4:" + result4.toList)
    
    //输出
    result1:List((shenzhen,32.6), (shanghai,29.3), (guangzhou,32.43333333333333), (beijing,27.86666666666667))
    result2:List((shenzhen,32.6), (shanghai,29.3), (guangzhou,32.43333333333333), (beijing,27.86666666666667))
    result3:List((shenzhen,32.6), (shanghai,29.3), (guangzhou,32.43333333333333), (beijing,27.86666666666667))
    result4:List((shenzhen,32.6), (shanghai,29.3), (guangzhou,32.43333333333333), (beijing,27.86666666666667))
    
    展开全文
  • Scala面向对象编程练习1 类2 对象 1 类 编写一个 Time 类,加入只读属性 hours 和 minutes,和一个检查某一时刻是否早于另一时刻的方法 before(other:Time):Boolean。Time 对象应该以 new Time(hrs,min)方式构建。 ...

    Scala面向对象编程练习

    1 类

    • 编写一个 Time 类,加入只读属性 hoursminutes,和一个检查某一时刻是否早于另一时刻的方法 before(other:Time):BooleanTime 对象应该以 new Time(hrs,min)方式构建。
    class Time(val hrs:Int,val min:Int){
      val hours = hrs
      val minutes = min
    
      def before(other:Time): Boolean ={
        if(other.hours > this.hours){
          return true
        }
        if(other.hours == this.hours){
          if(other.minutes > this.minutes){
            return false
          }
        }
        return false
      }
    }
    
    
    • 创建一个 Student 类,加入可读写的 JavaBeans 属性 name(类型为 String)和 id(类型为 Long)。有哪些方法被生产? (用 javap 查看。 )你可以在 Scala 中调用 JavaBeansgettersetter 方法吗?
    class Student{
      @BeanProperty var id:Long = _
      @BeanProperty var name:String = _
    }
    
    

    javap -c 查看反编译代码:

    C:\Users\lenovo>javap -c D:\AboutMyWork\IDEA-WorkSpace\ScalaDemo\ScalaExamples\target\classes\com\nefu\practice\Student.class
    Compiled from "A_Class_2_Stundent.scala"
    public class com.nefu.practice.Student {
      public long id();
        Code:
           0: aload_0
           1: getfield      #15                 // Field id:J
           4: lreturn
    
      public void id_$eq(long);
        Code:
           0: aload_0
           1: lload_1
           2: putfield      #15                 // Field id:J
           5: return
    
      public void setId(long);
        Code:
           0: aload_0
           1: lload_1
           2: putfield      #15                 // Field id:J
           5: return
    
      public java.lang.String name();
        Code:
           0: aload_0
           1: getfield      #24                 // Field name:Ljava/lang/String;
           4: areturn
    
      public void name_$eq(java.lang.String);
        Code:
           0: aload_0
           1: aload_1
           2: putfield      #24                 // Field name:Ljava/lang/String;
           5: return
    
      public void setName(java.lang.String);
        Code:
           0: aload_0
           1: aload_1
           2: putfield      #24                 // Field name:Ljava/lang/String;
           5: return
    
      public long getId();
        Code:
           0: aload_0
           1: invokevirtual #30                 // Method id:()J
           4: lreturn
    
      public java.lang.String getName();
        Code:
           0: aload_0
           1: invokevirtual #33                 // Method name:()Ljava/lang/String;
           4: areturn
    
      public com.nefu.practice.Student();
        Code:
           0: aload_0
           1: invokespecial #37                 // Method java/lang/Object."<init>":()V
           4: return
    }
    

    2 对象

    • 编写一个 Conversions 对象,加入 inchesToCentimeters,gallonsToLitersmilesToKilometers 方法
    class Conversions{
      def inchesToCentimeters(inches:Double):Double={
        /*
        1英寸(in)=2.54厘米(cm)
         */
        2.54 * inches
      }
    
      def gallonsToLiters(gallons:Double):Double={
        /*
        1美制加仑(us gal)=3.7854118公升(l)
         */
        3.7854118 * gallons
      }
    
      def milesToKilometers(miles:Double):Double={
        /*
        1英里(mi)=1.609344千米(km)
         */
        miles * 1.609344
      }
    }
    
    
    • 定义一个 Point 类和一个伴生对象,使得我们可以不用 new 而直接用 Point(3,4)来构造 Point 实例 apply 方法的使用
    object Point {
      def apply(x: Int, y: Int): Point = new Point(x, y)
    }
    class Point(x:Int = 0,y:Int = 0){
    }
    
    • 编写一个 Scala 应用程序,使用 App 特质,以反序打印命令行参数,用空格隔开。举例来说,scala Reverse Hello World 应该打印 World Hello
    object B_Object_3_Reverse extends App {
      args.reverse.mkString(" ")
    }
    
    • 编写一个扑克牌 4 种花色的枚举,让其 toString 方法分别返回♣,♦,♥,♠,并实现一个函数,检查某张牌的花色是否为红色
    object Poker extends Enumeration {
      //scala里的类型,除了在定义class,trait,object时会产生类型,
      // 还可以通过type关键字来声明类型。
      type Poker = Value  //type相当于声明一个类型别名 用Poker代替Value类型
    
      val plumBlossom = Value("♣")
      val squarePiece = Value("♦")
      val hearts = Value("♥")
      val spades = Value("♠")
    
      def isRed(poker:Poker): Boolean ={
        poker == hearts || poker == squarePiece
      }
    
      override def toString(): String = {
        Poker.values.mkString(",")
      }
    }
    
    • 练习使用包的各种声明方式,并查看他们的不同
    class Statement{
      /*
      1.在 Scala 中, import 语句可以出现在任何地方,
      并不仅限于文件顶部。
       */
      /*
      2.在 Java 中如果想要导入包中所有的类,可以通过通配符星号,
       Scala 中采用下划线
       */
      import java.util._
      println(Math.random())
    
      /*
      3.如果不想要某个包中全部的类,而是其中的几个类,可以采用选取器(大括号)
       */
      import scala.collection.mutable.{HashMap}
       var map = new HashMap()
    }
    
    • 编写一段程序,将 Java 哈希映射中的所有元素拷贝到 Scala 哈希映射。用引入语句重命名这两个类。
        import java.util.{HashMap=>JavaHashMap}
        import scala.collection.mutable.{HashMap=>ScalaHashMap}
    
        var jhm = new JavaHashMap[String,String]()
        var shm = new ScalaHashMap[String,String]()
    
        jhm.put("a","1");
        jhm.put("b","2");
        jhm.put("c","3");
    
        for(key <- jhm.keySet().toArray()){
          shm += (key.asInstanceOf[String] -> jhm.get(key))
        }
    
        println(shm.mkString(" "))
    

    3 继承

    • 扩展如下的 BankAccount 类,新类 CheckingAccount 对每次存款和取款都收取 1美元的手续费
    class BankAccount(initialBalance:Double){
      private var balance = initialBalance
      def deposit(amount:Double) = { balance += amount; balance}
      def withdraw(amount:Double) = {balance -= amount; balance}
    }
    
    class CheckingAccount(initialBalance:Double) extends BankAccount(initialBalance){
      private var balance = initialBalance
      override def deposit(amount:Double) = { balance += (amount - 1); balance}
      override def withdraw(amount:Double)={balance -= (amount + 1); balance}
    }
    
    
    • 扩展前一个练习的 BankAccount 类,新类 SavingsAccount 每个月都有利息产生
      (earnMonthlyInterest 方法被调用),并且有每月三次免手续费的存款或取款。在earnMonthlyInterest 方法中重置交易计数。
      override def deposit(amount:Double) = {
        if(this.monthlyCount < 4) {
          this.monthlyCount = this.monthlyCount + 1
          super.deposit(initialBalance)
        }else{
          super.deposit(initialBalance - 1)
        }
      }
    
      override def withdraw(amount:Double) = {
        if(this.monthlyCount < 4) {
          this.monthlyCount = this.monthlyCount + 1
          super.withdraw(initialBalance)
        }else{
          super.withdraw(initialBalance + 1)
        }
      }
    
      def earnMonthlyInterest(): Unit ={
        this.monthlyCount = 0
      }
    
    • 定义一个抽象类 Item,加入方法 pricedescriptionSimpleItem 是一个在构造器中给出价格和描述的物件。利用 val 可以重写 def 这个事实。 Bundle 是一个可以包含其他物件的物件。其价格是打包中所有物件的价格之和。同时提供一个将物件添加到打包当中的机制,以及一个适合的 description 方法
    abstract class Item{
      def price():Double
      def description():String
    
      override def toString() {
        println("price is: " + price() + ", description is: " + description())
      }
    }
    class SimpleItem(val price:Double,val description:String) extends Item{
    
    }
    class Bundle extends Item {
      val items = new ArrayBuffer[Item]()
      def addItem(item: Item): Unit ={
        items += item
      }
    
      override def price(): Double = {
        var sumPrice:Double = 0d
        this.items.foreach(sumPrice +=  _.price())
        sumPrice
      }
    
      override def description(): String = {
        items.mkString(" ")
      }
    }
    
    • 设计一个 Point类,其 x和 y坐标可以通过构造器提供。提供一个子类 LabeledPoint,其构造 器 接 受 一 个 标 签 值 和 x,y 坐 标 , 比 如 :new LabeledPoint( “BlackThursday” ,1929,230.07)
    class Point(x:Double,y:Double){
    
    }
    
    class LabeledPoint(Label:String,x:Double,y:Double) extends Point{
    }
    
    • 定义一个抽象类 Shape,一个抽象方法 centerPoint,以及该抽象类的子类 Rectangle和 Circle。为子类提供合适的构造器,并重写 centerPoint 方法
    abstract class Shape{
      def centerPoint()
    }
    
    class Rectangle(long: Double,width:Double) extends Shape {
      override def centerPoint(): Unit = ???
    }
    
    class Circle(radius:Double) extends Shape {
      override def centerPoint(): Unit = ???
    }
    
    • 提供一个 Square 类,扩展自 java.awt.Rectangle 并且是三个构造器:一个以给定的端点和宽度构造正方形,一个以(0,0)为端点和给定的宽度构造正方形,一个以(0,0)为端点,0 为宽度构造正方形
    class Square(point:Point,width:Int) extends java.awt.Rectangle(point.x,point.y,width,width){
      def this(){
        this(new Point(0,0),0)
      }
      def this(width:Int){
        this(new Point(0,0),width)
      }
    }
    

    5 特质

    object E_Trait_RenctangleLike {
      def main(args: Array[String]): Unit = {
        val egg = new Ellipse2D.Double(5,10,20,30) with RenctangleLike
        println("x = " + egg.getX + " y = " + egg.getY)
        egg.translate(10,-10)
        println("x = " + egg.getX + " y = " + egg.getY)
        egg.grow(10,20)
        println("x = " + egg.getX + " y = " + egg.getY)
      }
    }
    
    trait RenctangleLike{
      this:Ellipse2D.Double=>
      def translate(x:Double,y:Double){
        this.x = x
        this.y = y
      }
      def grow(x:Double,y:Double){
        this.x += x
        this.y += y
      }
    }
    
    x = 5.0 y = 10.0
    x = 10.0 y = -10.0
    x = 20.0 y = 10.0
    

    6 类型参数

    • 定义一个不可变类 Pair[T,S], 带一个 swap 方法,返回组件交换过位置的新对偶
    class Pair[T,S](val t:T,val s:S){
      def swap() = new Pair(s,t)
    }
    
    • 定义一个可变类 Pair[T],带一个 swap 方法,交换对偶中组件的位置。
    class Pairs[T](val t:T,val s:T){
      def swap() = new Pairs(s,t)
    }
    
    • 给定类 Pair[T, S] ,编写一个泛型方法 swap,接受对偶作为参数并返回组件交换过位置的新对偶。
    class Pairss[T,S](val t:T,val s:S){
      def swap(t:T,s:T) = new Pairss(s,t)
    }
    
    • 编写一个泛型方法 middle,返回任何 Iterable[T]的中间元素。举例来说,middle(“World” )应得到’ r’
      def middle[T](iter:Iterable[T]):T={
        val array = iter.toArray
        array(array.length / 2)
      }
    
    • 给定可变类 Pair[S,T],使用类型约束定义一个 swap 方法,当类型参数相同时可以被调用。
    class Pair[S,T](val s:S,val t:S){
      def swap(s:S,t:T): Unit ={
        if(s.getClass == t.getClass) new Pair(t,s)
      }
    }
    
    展开全文
  • 【图文详细 】Scala——编程练习

    千次阅读 2018-12-19 21:58:53
    6、Scala 编程练习  6.1、99 乘法表  package com.mazh.scala.funny object Table99 { def main(args: Array[String]): Unit = { for (i &lt;- 1 to 9){ for (j &lt;- 1 to i){ printf(&...

    6、Scala 编程练习 

    6.1、99 乘法表 

    package com.mazh.scala.funny 
     
    object Table99 { 
     
      def main(args: Array[String]): Unit = { 
        for (i <- 1 to 9){ 
          for (j <- 1 to i){ 
            printf("%d*%d=%2d\t", i, j, (i*j)) 
          } 
          println() 
        } 
      } 
    } 

    其实也可以利用 scala 的语法特性,使用一句代码完成:

    for(a <- 1 to 9; b <- 1 to a) printf("%d*%d=%d%s", a, b, a*b, if(a==b) "\n" else "\t")

    或者:

    for(x<- 1 to 9;y<- 1 to x )print(s"$y*$x=${x*y}${if(x==y) "\n" else "\t"}") 

     

    6.2、Scala 版本的 WordCount 

    现在有一个数组变量读入了一段话形成了一个数组,求出这段话中的每个单词的出现次数, 简单来说,就是单词统计:

    val array = Array("hello huangbo", "hello xuzheng", "hello wangbaoqiang") 
     
    结果:

    array.flatMap(_.split(" ")).map( (_,1)).groupBy(t => t._1).map(t =>(t._1,t._2.length)) .toList.sortBy(t => t._2).reverse 

     

    6.3、Scala 版本的插入排序 InsertSort 

    package com.mazh.scala.sort 
     
    import scala.util.control.Breaks 
    
    object InsertSort { 
     
      def main(args: Array[String]): Unit = { 
     
        val array = Array(4,12,6,3,8,9,5) 
        val ab = array.toBuffer 
     
        // 创建 Breaks对象 
     val forLoop = new Breaks 
     
        for (i <- 1 until ab.length){ 
          val value_i = ab(i) 
     
          // 把需要可能 break的代码放在 breakable 中执行 
          forLoop.breakable{ 
            for (j <- 0 to i - 1){ 
     
              val value_j = ab(j) 
              if (value_j > value_i){ 
                ab.remove(i, 1) 
                ab.insert(j, value_i) 
     
                // 使用 break进行跳出 
                forLoop.break() 
              } 
            } 
          } 
        } 
        println(ab) 
      } 
    } 

     

    展开全文
  • scala练习

    千次阅读 2018-04-20 19:28:38
    //创建一个List val lst0 = List(1,7,9,8,0,3,5,4,6,2) //将lst0中每个元素乘以10后生成一个新的集合 解析 : lst0.map(_*10) //将lst0中的偶数取出来生成一个新的集合 解析 : lst0.filter(_%2==0) //将...
  • Scala 高级编程练习

    2019-07-21 19:38:08
    定义自己的控制结构,使它语言内置的用法一样 package exp object Main { def enableCustomerIF = false; def main(args: Array[String]): Unit = IF(1 / 0 == 0) // 这里就不用写 ...println("hell...
  • scala练习

    2020-07-17 17:51:11
    本文为scala练习,可以检验你学的怎么样,也是自己检查自己的不错文档
  • scala习题精选100道,每道都有人工分析,技术点原理,不只是简单的答案
  • Scala函数式编程课后习题答案(第三章)
  • spark上使用scala及python编程练习

    千次阅读 2017-03-14 22:05:22
    本博文以此为蓝本,利用scala和python两种语言简单实践了一下实验内容,有利于增进认识。实现的功能为统计README.md文件下字符a和字符b分别有多少个。scala版本计算 安装 sbt SBT(Simple Build Tool)是一个现代...
  • 本文适合了解Scala编程的初级人员参考,至少熟悉基本语法和控制流程以及函数基础。 2. 实际操作 (1)没有返回的函数:编写一个函数,从终端输入一个整数打印出对应的金字塔 分析: 1. 没有返回值的函数怎么声明...
  • Scala练习

    2018-11-30 21:12:56
    1.将list中的每个元素 * 2 生成一个新的集合,即用的是map,用来生成一个新的数组。 第一种: 1)val = Array(1,2,3,4) 2)val func1:Int =&gt; Int = x=&gt;x*2 3)val ints1: Array[Int] = arr.map(func1) ...
  • package com.AtomicTestimport java.io.FileWriter/** * A tiny little testing framework,to display results and to introduce & promote * unit testing early in the learning curve.To use in a script or A
  • Scala练习集---RDD编程

    2019-05-03 15:07:42
    创建RDD 读取外部数据集 SparkContext.parallelize()方法...scala> val lines = sc.textFile("file:///usr/local/spark/mycode/rdd/word.txt") lines: org.apache.spark.rdd.RDD[String] = file:///usr/local/sp...
  • 简介 在学习完Scala语言后,我们可以实现一个简单的RPC来巩固前面我们学习的Scala知识点,这里主要的知识点涉及样例类、模式匹配、类继承、隐式转化以及函数和方法,如果需要源码可以在我的Github上下载,地址是...
  • Scala练习

    2019-11-21 19:08:14
    1.针对下列Java循环编写一个Scala版本: for(int i=10;i>=0;i–) System.out.println(i); 2.一个空的块表达式{}的值是什么?类型是什么? 3.编写一个函数countdown(n:Int),打印从n到0的数字 4.编写函数计算x的n...
  • 目录 1.课程目标 1.1 目标:使用Akka实现一个简易版的spark通信框架 2.项目概述 2.1 需求 2.2 Akka简介 1.课程目标 ... 1.1 目标:使用Akka实现一个简易版的spark通信框架 ... 2....整个表只有1...
  • package com.lxuex.test.scala ...object scala_01 { def fib(n: Int): Int ={ @annotation.tailrec //尾调用优化 def local(n:Int,current: Int = 0,next: Int = 1): Int ={ if(n == 0 || n == 1){ ...
  • scala入门练习题一

    千次阅读 2018-11-20 19:16:04
    作业一: val list0=List(1,7,9,8,0,3,5,4,6,2) val list1=list0.map((x)=&gt;{x*10}) val list2=list0.filter((x)=&gt;{x%2==0}) val list3=list0.sortWith((x,y)=&gt;......
  • scala在线练习

    千次阅读 2016-02-03 21:25:28
    http://scala-exercises.47deg.com/koans#asserts
1 2 3 4 5 ... 20
收藏数 3,158
精华内容 1,263
热门标签
关键字:

scala编程练习