Scala学习总结

class & object

  • su: class 跟伴生对象能访问彼此的私有成员

    A class and its companion object can access each other’s private members

  • su: 单例对象可以继承一个超类同时混合traits的特性

    singleton objects extend a superclass and can mix in traits

  • su: 单例对象无法实例化参数

    One difference between classes and singleton objects is that singleton objects cannot take parameters, whereas classes can. Because you can’t instantiate a singleton object with the new keyword, you have no way to pass parameters to it. Each singleton object is implemented as an instance of a synthetic class referenced from a static variable, so they have the same initialization semantics as Java statics.

  • su: 没有伴生类的独立对象

    A singleton object that does not share the same name with a companion class is called a standalone object

  • su: 默认的隐式导入java.lang 和 scala, 这就是为啥一些方法如print和assert可以直接使用

    Scala implicitly imports members of packages java.lang and scala, as well as the members of a singleton object named Predef, into every Scala source file. Predef, which resides in package scala, contains many useful methods. For example, when you say println in a Scala source file, you’re actually invoking println on Proofed. (Predef.println turns around and invokes Console.println, which does the real work.) When you say assert, you’re invoking Predef.assert.

  • su: 文件命名

    in Scala, you can name .scala files anything you want, no matter what Scala classes or code you put in them. In general in the case of non-scripts

Basic Types and Operations

  • su: 小写类型的会在后面的版本中废弃,所以最好使用大写的类型

    In honor of this community-driven choice, the lower case variants may be deprecated or even removed in a future version of Scala, so you would be wise indeed to go with the community flow and say Int, not int, in your Scala code

    1
    2
    def box(x : scala.Int) : java.lang.Integer = { /* compiled code */ }
    def unbox(x : java.lang.Object) : scala.Int = { /* compiled code */ }
  • su: String的换行原始字符串

    1
    2
    3
    4
    println("""Welcome to Ultamix 3000.
    Type "HELP" for help.""") // 这个方法会把type前面的空格包含进入
    println("""|Welcome to Ultamix 3000.
    |Type "HELP" for help.""".stripMargin) // 每行前面加上管道符|,调用stripMargin方法可以移除空格
  • su: Symbol literals(Symbol 字面量对象)

    symbols are interned. If you write the same symbol literal twice, both expressions will refer to the exact same Symbol object
    interned拘禁的这个特性跟java的String字面量池是等同的,String类内部维护一个字符串池(strings pool),当调用String的intern()方法时,如果字符串池中已经存在该字符串,则直接返回池中字符串引用,如果不存在,则将该字符串添加到池中,并返回该字符串对象的引用。执行过intern()方法的字符串,就说这个字符串被拘禁了(interned)。默认情况下,代码中的字符串字面量和字符串常量值都是被拘禁的;
    Symbol类型的好处在于节省内存,同时快速比较,Map<Symbol, Data>根据一个Symbol对象,可以快速查询相应的Data, 而Map<String, Data>的查询效率则低很多,Java的Map<String, Data>也可以实现这个的功能,但需要显式地调用intern()方法。

    1
    2
    scala> val s = 'aSymbol
    s: Symbol = 'aSymbol
  • su:Operators are methods

    1
    2
    3
    4
    5
    scala> val sum = 1 + 2    // Scala invokes (1).+(2)
    sum: Int = 3

    scala> val longSum = 1 + 2L // Scala invokes (1).+(2L)
    longSum: Long = 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ChecksumAccumulator{
private var sum=0
def add(b:Byte) :Unit = sum +=b
def checksum() : Int = ~ (sum & 0xFF) +1
}

object ChecksumAccumulator {
private val cache = Map [String, Int]()
def calculate(s:String) : Int =
if(cache.contains(s))
cache(s)
else {
val acc=new ChecksumAccumulator
for( c <- s)
acc.add(c.toByte)
val cs=acc.checksum()
cache += ( s -> cs)
cs
}
}
1
2
3
4
5
var filename="default.txt"
if(!args.isEmpty)
filename =args(0)

val filename= if(!args.isEmpty) args(0) else "default.txt"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
for (a <- 1 to 3) {
println("Value of a: " + a)
}

Value of a: 1
Value of a: 2
Value of a: 3

for (b <- 1 until 3) {
println("Value of b: " + b);
}

Value of b: 1
Value of b: 2

for (a <- 1 to 2; b <- 1 to 2) {
println("Value of a: " + a);
println("Value of b: " + b);
}

Value of a: 1
Value of b: 1
Value of a: 1
Value of b: 2
Value of a: 2
Value of b: 1
Value of a: 2
Value of b: 2

val numList1 = List(1, 2, 3);
for (a <- numList1) {
println("Value of a: " + a);
}

Value of a: 1
Value of a: 2
Value of a: 3

val numList2 = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (a <- numList2
if a != 3; if a < 8) {
println("Value of a: " + a);
}

Value of a: 1
Value of a: 2
Value of a: 4
Value of a: 5
Value of a: 6
Value of a: 7

val numList = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
val retVal = for {a <- numList if a != 3; if a < 8} yield a
// Now print returned values using another loop.
for (a <- retVal) {
println("Value of a: " + a);
}

Value of a: 1
Value of a: 2
Value of a: 4
Value of a: 5
Value of a: 6
Value of a: 7
1
2
3
4
5
6
7
val firstArg = if (args.length >0 ) args(0) else ""
val friend = firstArg match {
case "salt" => "pepper"
case "chips" => "salsa"
case "eggs" => "bacon"
case _ => "huh"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import scala.util.control.Breaks._
object BreakDemo {
def main(args: Array[String]) {
breakable {
for (i <- 1 to 10) {
if (i == 5) break() else println(i)
}
}
}
}

import scala.util.control.Breaks._
object ContinueDemo {
def main(args: Array[String]) {
for (i <- 1 to 10) {
breakable {
if (i == 5) break() else println(i)
}
}
}
}

object ContinueDemo {
def main(args: Array[String]) {
printNext(1)
}

def printNext(i: Int): Unit = {
if (i > 10) Unit
else if (i == 5) printNext(i + 1)
else {
println(i)
printNext(i + 1)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 嵌套函数例子
object LongLines {
// 类成员函数
def processFile(filename: String, width: Int) {
// 局部函数
def processLine(line: String) {
if (line.length > width) // 可以访问外部函数的成员变量 width、filename
println(filename + ":" + line.trim)
}

val source = Source.fromFile(filename)
for (line <- source.getLines())
processLine(line)
}
}
1
2
3
4
5
6
7
8
9
10
11
def add(x: Int, y: Int) : Int = {
x + y
}
val sum: (Int, Int) => Int = add
println(sum) // <function2>

val sum1: (Int, Int) => Int = (x, y) => x + y
println(sum1) // <function2>

val sum2 = (x:Int, y:Int) => x + y
println(sum2) // <function2>

val sparkSession = SparkSession.builder().config(itemRDD.sparkContext.getConf).getOrCreate()