Scala语法篇

scala,语法 · 浏览次数 : 21

小编点评

**排版内容** **1. 迭代器定义** ```scala Iterator[A] ``` **2. 迭代器方法** * `hasNext()`:检查是否有可返回的元素。 * `next()`:获取迭代器的下一个元素。 * `++`:合并两个迭代器。 * `filter`:返回满足条件的元素。 * `filterNot`:返回不满足条件的元素。 * `find`:返回第一个满足条件的元素。 * `flatMap`:针对迭代器序列中的每个元素应用函数。 * `forAll`:对每个元素执行指定的程序。 * `hasDefiniteSize`:检查迭代器元素个数是否有限。 * `length`:返回迭代器元素数量。 * `map`:将每个元素映射到一个新的元素。 * `max`:返回迭代器中元素的最大值。 * `min`:返回迭代器中元素中最小的值。 * `mkString`:将迭代器所有元素转换成字符串。 * `mkString(sep)`:将迭代器所有元素转换成字符串,并指定分隔符。 * `nonEmpty`:检查容器是否包含元素。 * `padTo`:将指定长度的元素追加到容器。 * `patch`:返回一个新迭代器,其中自第 from 个元素开始的 replaced 个元素被迭代器所指元素替换。 * `product`:返回迭代器所指数值型元素的积。 * `sameElements`:判断两个迭代器参数是否依次返回相同元素。 * `seq`:返回一个新的迭代器,指向迭代器所指向的序列中从开始于第 from 个元素、结束于第 last 个元素的片段。 * `sum`:返回迭代器所指数值型元素的和。 * `take`:返回前 n 个元素的新迭代器。 * `toArray`:将迭代器指向的所有元素归入数组并返回。 * `toBuffer`:将迭代器指向的所有元素拷贝至缓冲区 Buffer。 * `toIterable`:Returns an Iterable containing all elements of this traversable or iterator. * `toIterator`:把迭代器的所有元素归入一个Iterator容器并返回。 * `toList`:把迭代器的所有元素归入列表并返回。 * `toMap`:将键值对映射到一个Map并返回。 * `toSeq`:将代器的所有元素归入一个Seq容器并返回。 * `toString`:将迭代器转换为字符串。 * `zip`:返回两个迭代器,指向分别由迭代器和指定的迭代器 that 元素一一对应而成的二元组序列。

正文

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),样例类是种特殊的类,经过优化以用于模式匹配。

迭代器

Scala Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。迭代器 it 的两个基本操作是 nexthasNext。调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。调用 it.hasNext() 用于检测集合中是否还有元素。让迭代器 it 逐个返回所有元素最简单的方法是使用 while 循环:

object Test {
   def main(args: Array[String]) {
      val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
      
      while (it.hasNext){
         println(it.next())
      }
   }
}

下表列出了Scala Iterator常用的方法:

序号 方法及描述
1 def hasNext: Boolean如果还有可返回的元素,返回true。
2 def next(): A返回迭代器的下一个元素,并且更新迭代器的状态
3 def ++(that: => Iterator[A]): Iterator[A]合并两个迭代器
4 def ++[B >: A](that :=> GenTraversableOnce[B]): Iterator[B]合并两个迭代器
5 def addString(b: StringBuilder): StringBuilder添加一个字符串到 StringBuilder b
6 def addString(b: StringBuilder, sep: String): StringBuilder添加一个字符串到 StringBuilder b,并指定分隔符
7 def buffered: BufferedIterator[A]迭代器都转换成 BufferedIterator
8 def contains(elem: Any): Boolean检测迭代器中是否包含指定元素
9 def copyToArray(xs: Array[A], start: Int, len: Int): Unit将迭代器中选定的值传给数组
10 def count(p: (A) => Boolean): Int返回迭代器元素中满足条件p的元素总数。
11 def drop(n: Int): Iterator[A]返回丢弃前n个元素新集合
12 def dropWhile(p: (A) => Boolean): Iterator[A]从左向右丢弃元素,直到条件p不成立
13 def duplicate: (Iterator[A], Iterator[A])生成两个能分别返回迭代器所有元素的迭代器。
14 def exists(p: (A) => Boolean): Boolean返回一个布尔值,指明迭代器元素中是否存在满足p的元素。
15 def filter(p: (A) => Boolean): Iterator[A]返回一个新迭代器 ,指向迭代器元素中所有满足条件p的元素。
16 def filterNot(p: (A) => Boolean): Iterator[A]返回一个迭代器,指向迭代器元素中不满足条件p的元素。
17 def find(p: (A) => Boolean): Option[A]返回第一个满足p的元素或None。注意:如果找到满足条件的元素,迭代器会被置于该元素之后;如果没有找到,会被置于终点。
18 def flatMap[B](f: (A) => GenTraversableOnce[B]): Iterator[B]针对迭代器的序列中的每个元素应用函数f,并返回指向结果序列的迭代器。
19 def forall(p: (A) => Boolean): Boolean返回一个布尔值,指明 it 所指元素是否都满足p。
20 def foreach(f: (A) => Unit): Unit在迭代器返回的每个元素上执行指定的程序 f
21 def hasDefiniteSize: Boolean如果迭代器的元素个数有限则返回 true(默认等同于 isEmpty)
22 def indexOf(elem: B): Int返回迭代器的元素中index等于x的第一个元素。注意:迭代器会越过这个元素。
23 def indexWhere(p: (A) => Boolean): Int返回迭代器的元素中下标满足条件p的元素。注意:迭代器会越过这个元素。
24 def isEmpty: Boolean检查it是否为空, 为空返回 true,否则返回false(与hasNext相反)。
25 def isTraversableAgain: BooleanTests whether this Iterator can be repeatedly traversed.
26 def length: Int返回迭代器元素的数量。
27 def map[B](f: (A) => B): Iterator[B]将 it 中的每个元素传入函数 f 后的结果生成新的迭代器。
28 def max: A返回迭代器迭代器元素中最大的元素。
29 def min: A返回迭代器迭代器元素中最小的元素。
30 def mkString: String将迭代器所有元素转换成字符串。
31 def mkString(sep: String): String将迭代器所有元素转换成字符串,并指定分隔符。
32 def nonEmpty: Boolean检查容器中是否包含元素(相当于 hasNext)。
33 def padTo(len: Int, elem: A): Iterator[A]首先返回迭代器所有元素,追加拷贝 elem 直到长度达到 len。
34 def patch(from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B]返回一个新迭代器,其中自第 from 个元素开始的 replaced 个元素被迭代器所指元素替换。
35 def product: A返回迭代器所指数值型元素的积。
36 def sameElements(that: Iterator[_]): Boolean判断迭代器和指定的迭代器参数是否依次返回相同元素
37 def seq: Iterator[A]返回集合的系列视图
38 def size: Int返回迭代器的元素数量
39 def slice(from: Int, until: Int): Iterator[A]返回一个新的迭代器,指向迭代器所指向的序列中从开始于第 from 个元素、结束于第 until 个元素的片段。
40 def sum: A返回迭代器所指数值型元素的和
41 def take(n: Int): Iterator[A]返回前 n 个元素的新迭代器。
42 def toArray: Array[A]将迭代器指向的所有元素归入数组并返回。
43 def toBuffer: Buffer[B]将迭代器指向的所有元素拷贝至缓冲区 Buffer。
44 def toIterable: Iterable[A]Returns an Iterable containing all elements of this traversable or iterator. This will not terminate for infinite iterators.
45 def toIterator: Iterator[A]把迭代器的所有元素归入一个Iterator容器并返回。
46 def toList: List[A]把迭代器的所有元素归入列表并返回
47 def toMap[T, U]: Map[T, U]将迭代器的所有键值对归入一个Map并返回。
48 def toSeq: Seq[A]将代器的所有元素归入一个Seq容器并返回。
49 def toString(): String将迭代器转换为字符串
50 def zip[B](that: Iterator[B]): Iterator[(A, B)返回一个新迭代器,指向分别由迭代器和指定的迭代器 that 元素一一对应而成的二元组序列

与Scala语法篇相似的内容:

Scala语法篇

Scala基础篇 数据类型 下表中列出的数据类型都是对象,可以直接对它们调用方法。 数据类型 描述 Byte 8位有符号补码整数。数值区间为 -128 到 127 Short 16位有符号补码整数。数值区间为 -32768 到 32767 Int 32位有符号补码整数。数值区间为 -21474836

[转帖]Kafka 核心技术与实战学习笔记(六)kafka线上集群部署方案

一.操作系统-Linux Kafka是JVM系的大数据框架kafka由Scala语言和Java语言编写而成,编译之后的源代码就是普通的".class"文件 使用Linux kafka客户端底层使用Java的selector,selector在Linux上的实现机制是epoll,由于在windows上

[转帖]Java和Scala的前世今生

第一部分:Java 计算机语言介绍 第一代语言:机器语言。指令以二进制代码形式存在 第二代语言:汇编语言。使用助记符表示一条机器指令 第三代语言:高级语言 C、Pascal、Fortran面向过程的语言 C++面向过程/面向对象 Java跨平台的纯面向对象的语言 .NET跨语言的平台 Python、

Rapid SCADA v6安装常见问题

用了很多年的Rapid SCADA v5,现在官网已经推出了v6,就简单写一下有关v6的安装指南吧。 本指南面向Windows用户,不适用于linux用户 步骤 从官网下载Rapid SCADA最新的RC版本的v6,然后运行压缩包内的ScadaSetup.exe程序。 FAQ 提示端口占用 Rapi

[转帖]tiup cluster scale-in

https://docs.pingcap.com/zh/tidb/stable/tiup-component-cluster-scale-in tiup cluster scale-in 命令用于集群缩容,缩容即下线服务,最终会将指定的节点从集群中移除,并删除遗留的相关文件。 下线特殊处理 由于 T

张量(Tensor)、标量(scalar)、向量(vector)、矩阵(matrix)

张量(Tensor)、标量(scalar)、向量(vector)、矩阵(matrix) Python Numpy 切片和索引(高级索引、布尔索引、花式索引) Python NumPy 广播(Broadcast) 张量(Tensor):Tensor = multi-dimensional array

[转帖]使用 TiUP 扩容缩容 TiDB 集群

https://docs.pingcap.com/zh/tidb/stable/scale-tidb-using-tiup TiDB 集群可以在不中断线上服务的情况下进行扩容和缩容。 本文介绍如何使用 TiUP 扩容缩容集群中的 TiDB、TiKV、PD、TiCDC 或者 TiFlash 节点。如未

[转帖]使用 TiUP 扩容缩容 TiDB 集群

https://docs.pingcap.com/zh/tidb/stable/scale-tidb-using-tiup TiDB 集群可以在不中断线上服务的情况下进行扩容和缩容。 本文介绍如何使用 TiUP 扩容缩容集群中的 TiDB、TiKV、PD、TiCDC 或者 TiFlash 节点。如未

[转帖]使用 TiUP 扩容缩容 TiDB 集群

https://docs.pingcap.com/zh/tidb/stable/scale-tidb-using-tiup TiDB 集群可以在不中断线上服务的情况下进行扩容和缩容。 本文介绍如何使用 TiUP 扩容缩容集群中的 TiDB、TiKV、PD、TiCDC 或者 TiFlash 节点。如未

百度飞桨(PaddlePaddle)- 张量(Tensor)

张量(Tensor)、标量(scalar)、向量(vector)、矩阵(matrix) 飞桨 使用张量(Tensor) 来表示神经网络中传递的数据,Tensor 可以理解为多维数组,类似于 Numpy 数组(ndarray) 的概念。与 Numpy 数组相比,Tensor 除了支持运行在 CPU 上