写给 Java 程序员的 Scala 快速入门

时间:2025-04-24 10:26:12

我平时主要是写 Java,有时候读源码如 Kafka 或者 Spark 会遇见 Scala 的语法,总觉得有点别扭。我总结了一下 Scala 和 Java 有差异的语法。目的就是快速入门,消除别扭

和 var

  • Scala 有两类变量:val 和 var
  • val 类似 Java 的 final 变量,一旦初始化就不能被重新赋值
  • var 可以被重新赋值
object Test {
   def main(args: Array[String]) {
        // 申明变量的关键字 var val
        var v1: String = "code"
        // 类型可以自动推断
        var v2 = 2
        // :类型,手动指定类型
        val v3: Double = 3.14
        // val 相当于常量,不能不能改变其引用的对象本身
        val v4 = 3
        // 但是可以改变其引用的对象的其他属性
        val v5 = Array(1, 2, 3)
        v5(1) = 10
    }
}

2.集合

List

List 的创建有两种方式

object Test {
   def main(args: Array[String]) {
        // 定义列表有两种写法 :: 和 List
        //定义 列表
        val empty = Nil
        // ::构造列表
        val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
        //定义 List
        val x = List(1, 2, 3, 4)
    }
}

元组

元祖就是一堆数据的不可变集合,通过 _下标 访问

object Test {
   def main(args: Array[String]) {
        val z1 = (10, "Runoob", 3.14, true)
        println(z1._3)
    }  
}       

3.循环

Scala 的 while 和 Java 一样,但是 for 循环差异很大

object Test {
   def main(args: Array[String]) {
    // for 循环不支持 continue 和 break
    // to 前闭后闭
    for (i <- 1 to 3) println(i)
    // reverse 倒序
    for (i <- (1 to 3).reverse) println(i)
    // 前闭后开
    for (i <- 1 until 3) println(i)
    //循环守卫 if 控制输出
    for (i <- 1 to 10 if i % 3 == 0) println(i)
    //循环守卫 if 控制输出
    for (i <- 1 to 3; j = 4 - i) println(j)
    // 双重 for 循环
    for (i <- 1 to 3; j <- 1 to 3) println(s"i=$i, j=$j, i+j=${i + j}")
    // 返回一个集合
    val x = for (i <- 1 to 10) yield i
     }
}       

4.函数

Scala 的函数,写法如下

def max(x: Int, y: Int): Int = {
  if (x > y) x
  else y
}

可以做为一个对象赋值给一个变量

object Test {
   def main(args: Array[String]) {
    def sayHello(name: String): String = {
      "Hello," + name
    }
    //Scala中的函数是一等公民,可以直接将函数作为值赋值给变量
    //将函数赋值给变量时,必须在函数后面加上“ _”或“(_)”
    val hi = sayHello _
    println(hi("Ada"))

    //也可以使用匿名函数 
    val hello = (name: String) => println("hello," + name)
    hello("MilkTea")
     }
}  

object 就是常说的伴生对象,伴生对象是这个类的单例,它的方法就是这个类的静态方法

class Account {
  val id = Account.newUniqueNumber()
  private var balance = 0.0

}

object Account {
  private var lastNumber = 0

  private def newUniqueNumber() = {
    lastNumber += 1
    lastNumber
  }
}

trait 相当于 Java 中的接口,但可以定义抽象方法,也可以定义字段和方法的实现

trait HasLegs {
    //抽象字段
    val legs: Int
    // 定义一个具体的方法
    def walk() {
      println("Use" + legs + "legs to walk")
    }
    // 定义一个抽象方法
    def fly()
}

class

样例类关键字 case 类

case class Person (age: Int, name: String)

它非常的强大:

  • 伴生对象:编译会产生两个class, 和Person$class. 编译器自动添加了一个伴 生对象object Person
  • apply()方法:伴生对象Person里面默认实现了创建对象的apply()方法,创建实例的时候不需要使用关键字 new,可以直接通过Person(age, name)得到一个实例对象
  • 字段默认加上了val:age和name都被定义成了val(final),也可修改为 var
  • case 类自动地为所有类字段定义 Getter 方法
  • toString()、hashCode()和equals() 使用age和name构建
  • 实现Serializable接口

8.模式匹配

等效于 switch

模式匹配类似于 Java switch

val m = 3

m match {
  case 1 => println("one")
  case 2 => println("two")
  case _ => println("many")
}

匹配不同类型

但是模式匹配又比 switch 功能更多,如可以匹配不同类型

object Test {
   def main(args: Array[String]) {
        println(matchTest2(1))
        println(matchTest2(6))
        println(matchTest2("two"))
        println(matchTest2("7"))
   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one" //匹配值
      case "two" => 2 //另一种类型的匹配值
      case y: Int => "" //类型匹配,相当于 instanceof
      case _ => "many" // 默认
   }
}

配合 Option

Option 表达一种对结果的不确定,有可能有值,有可能为空,经常和模式匹配勾搭在一起

object Test {
   def main(args: Array[String]) {
        val keywords = Map("scala" -> "option", "java" -> "optional")
        // 能不能获取
        println(display(keywords.get("java")))
        println(display(keywords.get("c")))
   }
   
def display(game: Option[String]) = game match {
    case Some(s) => s
    case None => "unkown"
  }
} 
  • Option 的目的是为了避免使用null,
  • Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None

9.高阶函数

高阶函数:接收函数作为参数的函数,或返回值为函数的函数,被称作高阶函数

object Test {
   def main(args: Array[String]) {
         def higherOrderHi(func: (String) => Unit, name: String): Unit = {
            func(name)
    }

    higherOrderHi(hello, "Higher")
   }
}    

常用高阶函数

object Test {
   def main(args: Array[String]) {
        // map: 对传入的每个元素都进行映射,返回一个处理后的元素
        Array(1, 2, 3, 4, 5).map(_ * 10)
        
        //foreach: 对传入的每个元素都进行处理,但是没有返回值
         Array(1, 2, 3, 4, 5).map(_ * 10).foreach(println _)
        
        //filter: 对传入的每个元素都进行条件判断,如果对元素返回true,则保留该元素,否则过滤掉该元素
        (1 to 50).filter(_ % 10 == 0)
        
        //reduceLeft: 从左侧元素开始,进行reduce操作,即先对元素1和元素2进行处理,然 后将结果与元素3处理,再将结果与元素4处理,依次类推,即为reduce
        (1 to 4).reduceLeft( _ * _)
   }
}     

10.闭包

闭包由代码和代码用到的任何非局部变量定义而成

object Test {
   def main(args: Array[String]) {
        def mulBy(factor: Double) = (x: Double) => factor * x
        
        // mulBy 和 3 构成一个闭包
        val triple = mulBy(3)
        val half = mulBy(0.5)
        println(s"${triple(14)} ${half(14)}")
   }
}