本文共 5576 字,大约阅读时间需要 18 分钟。
之前在学习Spark的过程中,学习课程里的实战内容都是用Scala语言来编写的,而我们知道Spark项目本身也是由Scala语言编写而成,觉得有必要深入了解和学习,所以也上网查找了一些学习路线和学习资源,希望做成一份简易的学习指南可以让自己可以更有框架性地学习这门语言,也顺便分享给需要的朋友。
1)官网的入门文档:https://docs.scala-lang.org/overviews/scala-book/introduction.html
2)官网标准文档,可查所有内容:https://docs.scala-lang.org/overviews/index.html
3)Scala语言规范:https://static.runoob.com/download/Scala语言规范.pdf
有了上面的资料之后,后面就是安排时间进行学习了,这里就先来启动Scala来简单编写一下一些简单语法:
def hellosam() { println("hello sam") } HelloWorld()
在Scala编程中要注意以下几点内容:
在Scala中标识符只能包括字符、数字和下划线,并且只能以字符和下划线开头,数字不能开头。如name、_value这些是合法,而 1people这些是非法的
运算标识符由一个或多个运算符组成,运算符是可以打印的 ASCII 码,比如:+
、*
、-
、/
、?
、:
、~
等等。
运算标识符有:+
、++
、:::
、``、:>
等等。
混合标识符由一个字符数字标识符、下划线和一个运算标识符组成,比如:unary_+
、var_=
。在这里,unary_+
定义了一个一元+
运算符,myvar_=
用来作为方法名称定义了一个赋值运算符。
用``符号包含任意字符都是文字标识符,如:
`name`
Scala的数据类型和Java完全一致。
数据类型 | 描述 |
---|---|
Byte | 8 位有符号值,范围:-128~127 |
Short | 16 位有符号值,范围:-32768~32767 |
Int | 32 位有符号值,范围:-2147483648~2147483647 |
Long | 64 位有符号值,范围:-9223372036854775808~9223372036854775807 |
Float | 32 位 IEEE754 单精度浮点数 |
Double | 64 位 IEEE754 双精度浮点数 |
Char | 16 位无符号 Unicode 字符,范围:U+0000~U+FFFF |
String | 字符串 |
Boolean | 布尔值:true / false |
Unit | 表示没有值 |
Null | 空或空引用 |
Nothing | 每一个其他类型的子类型,包括无值 |
Any | 任何类型的超类型,任何 object 都是 Any 类型的 |
AnyRef | 任何引用类型的超类型 |
我们通常通过val来声明值(也就是常量),声明过后就不能更改其值,不然会报错。
然后通过var来声明变量,它是可以被赋予不同的值的。
函数我们是通过def来定义的,需要为函数参数指定类型签名,其语法结构如下:
def functionName ([list of parameters]) : [return type] = { function body return [expr] }
看一个栗子:
def addOne(m: Int): Int = { return m + 1 } var res = addOne(5) println(res)
如果函数不带参数,调用的时候可以不写括号,函数体中的语句如果只有一条表达式,可以省略函数的大括号,如:
def addOne(): Int = 1 + 1 var res2 = addOne println(res2)
这里还有一个很神奇的通配符用法,那就是使用下划线_
表示不同上下文中的不同事物,可以看看下面的栗子:
def add(x: Int, y: Int) :Int = { return x + y } var add1 = add(1, _:Int) var add2 = add1(2) println(add2)
还有一种用法和上面的类似:
def add(x: Int)(y: Int) :Int = { return x + y } var add1 = add(1)(2) var add2 = add(2) _ var add3 = add2(3) println(add1) println(add3)
如果我们对于入参的数量没有限制,其实可以这样去写我们的函数:
// 把所有单词改为首字母大写 def capitalizeAll(args: String*) = { args.map { arg => arg.capitalize } } var str = capitalizeAll("hello", "sam") println(str)
类就是对方法和变量字段的抽象集成,我们可以在类中定义方法,然后反复使用,如下面栗子:
class Calculator { val brand: String = "SAMshare" def add(m: Int, n: Int): Int = m + n } val calc = new Calculator println(calc.brand) println(calc.add(1, 2))
在类中我们可以增加一个构造函数参数,从而来初始化内部状态的变量值,如下:
class Calculator(brand: String) { /** * 一个构造函数 */ val color: String = if (brand == "SAMshare") { "blue" } else if (brand == "new younger") { "black" } else { "white" } // 实例方法 def add(m: Int, n: Int): Int = m + n } // 你可以使用构造函数来构造一个实例 val calc = new Calculator("SAMshare") calc.color
这个很好理解,就是子类继承了父类的一些方法,从而来达到重复利用的效果。
class ScientificCalculator(brand: String) extends Calculator(brand) { def log(m: Double, base: Double) = math.log(m) / math.log(base) }
方法的重载就是即便方法名是一样的,但是可以从方法的参数个数或者类型上进行区分开来不同的方法,从而实现了方法的重载。
class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) { def log(m: Int): Double = log(m, math.exp(1)) }
我们可以定义一个抽象类,它可以定义一些方法但没有实现,所以也不能创建抽象类的实例,取而代之的是在子类上去定义这个方法的具体功能:
// 定义抽象类 abstract class Shape { def getArea():Int // subclass should define this } // 扩展抽象类 class Circle(r: Int) extends Shape { def getArea():Int = { r * r * 3 } } val c = new Circle(2)
这个名词对我来说还是蛮新的,它是一些字段和行为的集合,可以扩展或混入到类中,一个类可以扩展多个Traits。
trait Equal { def isEqual(x: Any): Boolean def isNotEqual(x: Any): Boolean = !isEqual(x) } class Point(xc: Int, yc: Int) extends Equal { var x: Int = xc var y: Int = yc def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x } object Test { def main(args: Array[String]) { val p1 = new Point(2, 3) val p2 = new Point(2, 4) val p3 = new Point(3, 3) println(p1.isNotEqual(p2)) println(p1.isNotEqual(p3)) println(p1.isNotEqual(2)) } } //false //true //true
Scala 提供了丰富的集合库,包括:列表(List)、集合(Set)、映射(Map)、选项(Option)、元组(Tuple)。
scala> val x1 = List(1, 2, 3, 4) x1: List[Int] = List(1, 2, 3, 4) scala> println(x1) List(1, 2, 3, 4) scala> val x2 = Set(1, 3, 5) x2: scala.collection.immutable.Set[Int] = Set(1, 3, 5) scala> println(x2) Set(1, 3, 5) scala> val x3 = Map("one" -> 1, "two" -> 2) x3: scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2) scala> println(x3) Map(one -> 1, two -> 2) scala> val x4 = (2, "two") x4: (Int, String) = (2,two) scala> println(x4) (2,two) scala> val x5:Option[Int] = Some(5) x5: Option[Int] = Some(5) scala> println(x5) Some(5)
这个问题其实很重要了,毕竟我们也知道 your time is limited,所以还是要分析一下,我在知乎上看到了一些回答还是很赞的。
我的回答是,是的,Scala是一门值得花时间去学习的语言。因为它自身的设计(以及其相关的生态)系希望把过去20年来一些计算机科学技术发展的成果,以一种尽可能友好(或者实用)的方式呈现在软件工程师面前,让开发人员更好地武装自己。你可以想象你在学习这门语言的路途上,能和全球的技术研发人员一起坐而论道。无论是如日中天的Spark,还是提供高效能框架的Actor, Kafka,为什么Scala能在Java雄霸JVM平台多年的情景下帮助这些新产品突围而出被研发广泛使用?并且产生足够大的影响让Java产生一些改变?这难道不是一个让你去了解和学习Scala的一个很好的动力吗?
—— neo lin · 知乎
而对于我自己,Scala在大数据处理这块是有很应用场景的,也并不用学习得很深入也可以在工作中应用起来,处理大数据,比如spark。而且据了解现在从事数据挖掘和机器学习,并不仅仅满足于简单的MapReduce了,需要在这个基础上开发各种分布式数据批处理框架,需要有函数式编程的习惯了,这块也是我要补的一块内容。说回Scala,在常用的工具中Spark和Kafka都是用Scala编写的,在工业界是很推荐使用Scala的。
转载地址:http://hhqsx.baihongyu.com/