Scala

Scala基础篇(持续更新中...)

数据类型

下表中列出的数据类型都是对象,可以直接对它们调用方法。

数据类型 描述
Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
Float 32 位, IEEE 754 标准的单精度浮点数
Double 64 位 IEEE 754 标准的双精度浮点数
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
Boolean true或false
Unit 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。
Null null 或空引用
Nothing Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。
Any Any是所有其他类的超类
AnyRef AnyRef类是Scala里所有引用类(reference class)的基类

表示Long类型,在数字后面添加L或者l作为后缀;浮点数后面有f或者F后缀时,表示Float类型,否则就是Double

变量

用关键词“var”声明变量,关键词"val"声明常量。

var myName : String = "gyt"
val myAge : Int = 21 

scala中不一定要指明数据类型,其数据类型通过变量或常量的初始值推断出来的,因此,在没有指明数据类型的情况下,必须要给出初始值。

访问修饰符

private关键词修饰,只能被当前类以及当前类的内部类访问到,外层类访问不到。

class Outer{
    class Inner{
        private def f(){
            println("f")
        }
        class InnerMost{
            f() // 正确
        }
    }
    (new Inner).f() //错误
}

protected关键词修饰,只能被当前类的子类访问。

package p {
    class Super {
        protected def f() {println("f")}
    }
    class Sub extends Super {
        f()
    }
    class Other {
        (new Super).f() //错误
    }
}

没有指定任何修饰符,默认为public,在任何地方都可以被访问。

条件和循环

以下是IF...ELSE语句实例。

object Test {
   def main(args: Array[String]) {
      var x = 30;

      if( x == 10 ){
         println("X 的值为 10");
      }else if( x == 20 ){
         println("X 的值为 20");
      }else if( x == 30 ){
         println("X 的值为 30");
      }else{
         println("无法判断 X 的值");
      }
   }
}

以下是一个使用了 i to j 语法(包含 j)的实例,箭头 <- 用于为变量 a 赋值。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      // for 循环
      for( a <- 1 to 10){
         println( "Value of a: " + a );
      }
   }
}

for 循环 中你可以使用分号;来设置多个区间,它将迭代给定区间所有的可能值。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      var b = 0;
      // for 循环
      for( a <- 1 to 3; b <- 1 to 3){
         println( "Value of a: " + a );
         println( "Value of b: " + b );
      }
   }
}

for 循环集合的语法如下。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      val numList = List(1,2,3,4,5,6);

      // for 循环
      for( a <- numList ){
         println( "Value of a: " + a );
      }
   }
}

你可以将 for 循环的返回值作为一个变量存储。

object Test {
   def main(args: Array[String]) {
      var a = 0;
      val numList = List(1,2,3,4,5,6,7,8,9,10);

      // for 循环
      var retVal = for{ a <- numList 
                        if a != 3; if a < 8
                      }yield a

      // 输出返回值
      for( a <- retVal){
         println( "Value of a: " + a );
      }
   }
}

函数式编程(重点)

函数式编程:对于相同的输入永远会得到相同的输出,而且没有任何可以观察的副作用,也不依赖外部的环境状态。参考什么是函数式编程?

Scala中函数是为完成某一功能的程序语句的集合,类中定义的函数称之为方法。下面是方法的一个实例。

object add{
   def addInt( a:Int, b:Int ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

可变参数:我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。

object Test {
   def main(args: Array[String]) {
        printStrings("Runoob", "Scala", "Python");
   }
   def printStrings( args:String* ) = {
      var i : Int = 0;
      for( arg <- args ){
         println("Arg value[" + i + "] = " + arg );
         i = i + 1;
      }
   }
}

默认参数: scala可以为函数参数指定默认参数值,使用了默认参数,你在调用函数的过程中可以不需要传递参数,这时函数就会调用它的默认参数值,如果传递了参数,则传递值会取代默认值。

object Test {
   def main(args: Array[String]) {
        println( "返回值 : " + addInt() );
   }
   def addInt( a:Int=5, b:Int=7 ) : Int = {
      var sum:Int = 0
      sum = a + b

      return sum
   }
}

匿名函数:箭头左边是参数列表,右边是函数体。

var inc = (x: Int) => {x+1}
var x = inc(7) - 1

//定义一个函数,以函数作为参数输入
def f(func: String => Unit): Unit = {
    func("gyt")
}
var fun = (name: String) => {println(name)}
f(fun)

传名调用:传递的不是具体的值,而是代码块。和一般的传值调用相比,每次使用传名调用时,解释器都会计算一次表达式的值。

def f1(): Int = {
    println("f1被调用")
    12
}
def f2(a: => Int): Unit = {
    println(a)
    println(a)
}
f2(f1())

至简原则

(1)函数中的return可以省略,以最后一行代码作为代码块的返回值。

def f1(name: String): String = {
    name
}

(2)如果函数体只有一行代码,可以省略花括号。

def f2(name: String): String = name

(3)如果编译器可以推断出来返回值,那么可以省略(:和返回值类型一起省略)。有意思的是,到这一步,scala函数的形式形如数学中的f(x) = y。

def f3(name: String) = name

(4)如果有return,则(3)不适用。

(5)如果返回值是Unit,可以省略等号和返回值,但是此时花括号不能省略。

def f4(name: String) {
    println(name)
}

(6)如果函数没有参数,那么调用它的时候可以直接用函数名。不用加“()”。

闭包:如果一个函数,访问到它的外部(局部)变量的值,那么这个函数和它所处的环境,称为闭包。

柯里化:将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。

object Test {
   def main(args: Array[String]) {
      val str1:String = "Hello, "
      val str2:String = "Scala!"
      println( "str1 + str2 = " +  strcat(str1)(str2) )
   }

   def strcat(s1: String)(s2: String) = {
      s1 + s2
   }
}

字符串

在 Scala 中,字符串的类型实际上是 Java String,它本身没有 String 类。

序号 方法及描述
1 char charAt(int index)返回指定位置的字符
2 int compareTo(Object o)比较字符串与对象
3 int compareTo(String anotherString)按字典顺序比较两个字符串
4 int compareToIgnoreCase(String str)按字典顺序比较两个字符串,不考虑大小写
5 String concat(String str)将指定字符串连接到此字符串的结尾
6 boolean contentEquals(StringBuffer sb)将此字符串与指定的 StringBuffer 比较。
7 static String copyValueOf(char[] data)返回指定数组中表示该字符序列的 String
8 static String copyValueOf(char[] data, int offset, int count)返回指定数组中表示该字符序列的 String
9 boolean endsWith(String suffix)测试此字符串是否以指定的后缀结束
10 boolean equals(Object anObject)将此字符串与指定的对象比较
11 boolean equalsIgnoreCase(String anotherString)将此 String 与另一个 String 比较,不考虑大小写
12 byte getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
13 byte[] getBytes(String charsetName使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
14 void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此字符串复制到目标字符数组
15 int hashCode()返回此字符串的哈希码
16 int indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引
17 int indexOf(int ch, int fromIndex)返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索
18 int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引
19 int indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
20 String intern()返回字符串对象的规范化表示形式
21 int lastIndexOf(int ch)返回指定字符在此字符串中最后一次出现处的索引
22 int lastIndexOf(int ch, int fromIndex)返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索
23 int lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引
24 int lastIndexOf(String str, int fromIndex)返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
25 int length()返回此字符串的长度
26 boolean matches(String regex)告知此字符串是否匹配给定的正则表达式
27 boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等
28 boolean regionMatches(int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等
29 String replace(char oldChar, char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的
30 String replaceAll(String regex, String replacement使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串
31 String replaceFirst(String regex, String replacement)使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串
32 String[] split(String regex)根据给定正则表达式的匹配拆分此字符串
33 String[] split(String regex, int limit)根据匹配给定的正则表达式来拆分此字符串
34 boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始
35 boolean startsWith(String prefix, int toffset)测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
36 CharSequence subSequence(int beginIndex, int endIndex)返回一个新的字符序列,它是此序列的一个子序列
37 String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串
38 String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串
39 char[] toCharArray()将此字符串转换为一个新的字符数组
40 String toLowerCase()使用默认语言环境的规则将此 String 中的所有字符都转换为小写
41 String toLowerCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为小写
42 String toString()返回此对象本身(它已经是一个字符串!)
43 String toUpperCase()使用默认语言环境的规则将此 String 中的所有字符都转换为大写
44 String toUpperCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为大写
45 String trim()删除指定字符串的首尾空白符
46 static String valueOf(primitive data type x)返回指定类型参数的字符串表示形式

数组

Scala 语言中提供的数组是用来存储固定大小的同类型元素。下面是声明数组的三种方式。

var z:Array[String] = new Array[String](3)
var zz = new Array[String](3)
var zzz = Array("Runoob", "Baidu", "Google")

模式匹配

一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

object Test {
   def main(args: Array[String]) {
      println(matchTest("two"))
      println(matchTest("test"))
      println(matchTest(1))
      println(matchTest(6))

   }
   def matchTest(x: Any): Any = x match {
      case 1 => "one"
      case "two" => 2
      case y: Int => "scala.Int"
      case _ => "many"
   }
}

实例中第一个 case 对应整型数值 1,第二个 case 对应字符串值 two,第三个 case 对应类型模式,用于判断传入的值是否为整型,相比使用isInstanceOf来判断类型,使用模式匹配更好。第四个 case 表示默认的全匹配备选项,即没有找到其他匹配时的匹配项,类似 switch 中的 default。

object Test {
   def main(args: Array[String]) {
        val alice = new Person("Alice", 25)
        val bob = new Person("Bob", 32)
        val charlie = new Person("Charlie", 32)
   
    for (person <- List(alice, bob, charlie)) {
        person match {
            case Person("Alice", 25) => println("Hi Alice!")
            case Person("Bob", 32) => println("Hi Bob!")
            case Person(name, age) =>
               println("Age: " + age + " year, name: " + name + "?")
         }
      }
   }
   // 样例类
   case class Person(name: String, age: Int)
}

使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。

热门相关:流鱼无恙   修真界败类   富贵不能吟   修真界败类   富贵不能吟