zoukankan      html  css  js  c++  java
  • Scala 基础(一)

    1. Scala 安装

    Scala 运行于Java平台(JVM,Java 虚拟机)上,并兼容现有的Java程序,Scala代码可以调用Java方法,访问Java字段,继承Java类和实现Java接口。在面向对象方面,Scala是一门非常纯粹的面向对象编程语言,也就是说,在Scala中,每个值都是对象,每个操作都是方法调用,有如下优点:

    • 强大并发性、支持函数式编程(简单),可更好支持分布式系统
    • 语法简洁,可提供优雅 API
    • 兼容 Java,运行速度快,可融合到 Hadoop 生态圈

    Hello World

    // 主函数名与文件名可不一致,区别于 Java
    object HelloWorld {
      def main(args: Array[String]): Unit = {
        println("Hello World!")
      }
    }
    

    参考文章:IDEA中配置Scala开发编译环境

    2. 基础

    2.1 基本操作

    • 变量:双引号
    • 语句后面可以没有分号
    • 注释:///* */
    • 终端退出 scala shell 环境:scala> :quit

    2.2 变量

    两种类型变量:

    • 可变 var:声明后可再赋值
    • 不可变 val:声明时必须初始化值,一旦声明不能赋值

    val 不可变变量

    scala> val name = "rose"                   
    name: String = rose                        
            
    // 重新赋值报错
    scala> name="lila"                         
    <console>:12: error: reassignment to val   
           name="lila"                         
               ^          
    
    // 显示指定数据类型
    scala> val name:String = "lila"
    name: String = lila
    
    scala> val name:java.lang.String = "john"
    name: String = john
    
    scala> println(name)
    john
    

    注意:Scala 在声明变量时可不显示地指定变量类型,它可根据值反推数据类型,也可以显示指定变量类型!Scala 的数据类型由 import java.lang._ 包提供,每个程序会隐士地导入所有,所以可以不用再导入


    var 可变变量

    scala> var age = 19
    age: Int = 19
    
    scala> age = 18
    age: Int = 18
    

    2.3 基本数据类型

    基本数据类型包括:Byte、Char、Short、Int、Long、Float、DoubleBoolean,这些数据类型每个都是一个 Scala 包,如:Intscala.Int

    字面量

    字面量包括整数字面量、浮点数字面量、布尔型字面量、字符字面量、字符串字面量、符号字面量、函数字面量和元组字面量:

    scala> val a = 123		// 整数字面量
    a: Int = 123
    
    scala> var a = 1.23		// 浮点数字面量
    a: Double = 1.23
    
    scala> var a = true		// 布尔字面量
    a: Boolean = true
    
    scala> var a = "ABC"	// 字符串字面量
    a: String = ABC
    
    scala> var a = "A"		// 字符字面量
    a: String = A
    

    Scala 可对字面量直接调用方法,如:

    // 整数字面量转换为字符串
    scala> 8.toString()
    res1: String = 8
    
    // 获取两个字符串都有的字符
    scala> "abc".intersect("bcd")
    res2: String = bc
    

    操作符

    Scala 的支持的操作符包括:加(+)、减(-) 、乘(*) 、除(/) 、余数(%)等,使用格式:

    // 两者等价
    a 操作符 b
    (a). 操作符 (b)
    

    示例:

    // 实际内部调用的就是 (5).+(3)
    scala> 5 + 3		
    res3: Int = 8
    
    scala> (5).+(3)
    res4: Int = 8
    
    // 递增、递减,区别于 Java 的 ++  --
    scala> var age = 18
    age: Int = 18
    
    scala> age -= 1
    
    scala> age
    res6: Int = 17
    

    2.4 Range

    Range 支持创建不同数据类型的数值序列,包括 Int、Long、Float、Double、Char、BigIntBigDecimal等,一般与 for 循环配合使用:

    // 生成一个 1 到 5 的整数序列,包括 5,步长默认为 1
    scala> 1 to 5
    res7: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
    
    scala> 1.to(5)
    res8: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)
    
    // 生成一个 1 到 5 的整数序列,不包括 5
    scala> 1 until 5
    res9: scala.collection.immutable.Range = Range(1, 2, 3, 4)
    
    // 指定步长
    scala> 1 to 22 by 2
    res10: scala.collection.immutable.Range = Range(1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21)
    
    scala> 0.5f to 5.9f by 0.8f
    res11: scala.collection.immutable.NumericRange[Float] = NumericRange(0.5, 1.3, 2.1, 2.8999999, 3.6999998, 4.5, 5.3)
    

    2.5 控制台输入输出

    scala> val name = "rose"	
    name: String = rose
    
    // 换行输出
    scala> println(name)
    rose
    
    // 不换行输出
    scala> print(name)
    rose
    
    scala> val age = 18
    age: Int = 18
    
    // 字符串格式化
    scala> printf("My name's %s age: %d.", name, age)
    My name's rose,age: 18.
    

    控制台读写数据

    读写方法:readInt、readDouble、readByte、readShort、readFloat、readLong、readChar、readBoolean、readLine,分别对应 9 中不同数据类型,前 8 种没参数,readLine 可不提供参数,也可以带一个字符串参数的提示:

    这些方法都属于对象 scala.io.StdIn,使用前必须导入,在控制台输入数据不会显示(回车后才会显示):

    scala> import io.StdIn._
    import io.StdIn._
    
    scala> var i = readInt()
    i: Int = 54
    
    scala> var f=readFloat()
    f: Float = 52.2
    
    scala> var b= readBoolean()
    b: Boolean = true
    
    scala> var info = readLine("please input your name: ")
    please input your name: info: String = rose
    
    scala> info
    res15: String = rose
    

    2.6 读写文件

    写文件

    scala> import java.io.PrintWriter
    import java.io.PrintWriter
    
    scala> val out = new PrintWriter("C:\Users\hj\Desktop\scala.txt")
    out: java.io.PrintWriter = java.io.PrintWriter@34604b32
    
    scala> for(i <- 1 to 5) out.println(i)
    
    scala> out.close()
    

    读文件

    scala> import scala.io.Source
    import scala.io.Source
    
    scala> val inputFile = Source.fromFile("C:\Users\hj\Desktop\scala.txt")
    inputFile: scala.io.BufferedSource = non-empty iterator
    
    scala> val lines = inputFile.getLines
    lines: Iterator[String] = non-empty iterator
    
    scala> for (line <- lines) println(line)
    1
    2
    3
    4
    5
    
    scala> inputFile.close()
    

    IDEA 中使用

    import scala.io.Source
    import java.io.PrintWriter
    
    
    object ReadWriteFile {
      def main(args: Array[String]): Unit = {
        readFile()
        writeFile()
      }
    
      def readFile(): Unit = {
        val inputFile = Source.fromFile("C:\\Users\\hj\\Desktop\\scala.txt")
        val lines = inputFile.getLines()
        for (line <- lines) {
          println(line)
        }
        inputFile.close()
      }
    
      def writeFile(): Unit = {
        val out = new PrintWriter("C:\\Users\\hj\\Desktop\\scala.txt")
        for (i <- 1 to 10 by 2) {
          out.println(i)
        }
        out.close()
      }
    }
    

    2.7 异常处理

    import java.io.{FileNotFoundException, FileReader, IOException}
    
    object TryCatch {
      def main(args: Array[String]): Unit = {
        try {
          val f = new FileReader("input.txt")
        } catch {
          case ex: FileNotFoundException =>
            println("文件不存在!", ex)
          case ex: IOException =>
            println("IO 错误操作", ex)
        } finally {
          println("Exiting finally...")
        }
      }
    }
    
    (文件不存在!,java.io.FileNotFoundException: input.txt (系统找不到指定的文件。))
    Exiting finally...
    

    3. 控制结构

    3.1 if 条件表达式

    object LoopTest {
      def main(args: Array[String]): Unit = {
        val score = 99
        if (score > 80) {
          println("A")
        } else if (score < 80 && score > 70) {
          println("B")
        }else {
          println("C")
        }
      }
    
    }
    

    if 条件表达的值可赋值给变量

    scala> val x = 8                                          
    x: Int = 8                                                
                                                              
    scala> val y = if (x>0) 1 else -1                         
    y: Int = 1                                                
    

    3.2 while 循环

    object LoopTest {
      def main(args: Array[String]): Unit = {
        test_while()
      }
    
      def test_while(): Unit = {
        var i = 15
        while (i <= 30) {
          i += 1
        }
        println(i)
    
        var m = 10
        do {
          m += 1
        } while (m < 31)
        println(m)
      }
    }
    

    3.3 for 循环

    格式:

    // 变量<-表达式 部分被称为生成器
    for (变量<-表达式) 语句块
    
    scala> for (i <- 1 to 6) println(i)                 
    1                                                   
    2                                                   
    3                                                   
    4                                                   
    5                                                   
    6                                                   
      
    // 设置步长为 2
    scala> for (i <- 1 to 6 by 2) println(i)            
    1                                                   
    3                                                   
    5                                                   
            
    // 设置守卫,满足条件才能返回
    scala> for (i <- 1 to 6 by 3 if i%2==0) println(i)  
    4                                                   
    

    多生成器

    类似于多个 for 循环

    scala> for (i <- 1 to 3; j <- 2 to 5) println(i*j)
    2
    3
    4
    5
    4
    6
    8
    10
    6
    9
    12
    15
    

    守卫:

    scala> for (i <- 1 to 3 if i==2; j <- 2 to 5 if j==3) println(i*j)
    6
    

    for 推导式

    通过 for 循环遍历一个或多个集合,对集合中的元素进行 推导,从而计算得到新的集合,用于后续处理:

    object LoopTest {
      def main(args: Array[String]): Unit = {
        test_for()
      }
    
      def test_for(): Unit ={
        var abc = for (i <- 1 to 5 if i%2==0) yield i
    
        for (a <- abc) {
          println(a)
        }
      }
    }
    

    abc 是变量,yield 会将结果存储到集合中,循环结束后将返回该集合:

    2
    4
    

    4. 数据结构

    常用数据结构:

    • 容器 Collection
    • 列表 LIst
    • 集合 Set
    • 映射 Map
    • 迭代器 Iterator
    • 数组 Array
    • 元组 Tuple

    4.1 容器

    Scala 有一套丰富的容器库,包括:列表、数组、集合、映射等,根据元素组织方式和操作方式,可分为:有序和无序、可变和不可变等不同容器类别,容器的三个类:

    scala.collection、scala.collection.mutable、scala.collection.immutable

    4.2 列表

    列表是一种共享相同类型不可变的对象序列,一旦定义值不能改变,声明时必须初始化值:

    // 因为是不可变集合,索引列表存在 scala.collection.immutable 中
    scala> import scala.collection.immutable
    import scala.collection.immutable
    
    scala> var strList = List("A", "B", "C")
    strList: List[String] = List(A, B, C)
    
    // 获取第一个元素
    scala> strList.head
    res1: String = A
    
    // 获取除第一个元素后的所有元素集合(新的列表)
    scala> strList.tail
    res2: List[String] = List(B, C)
    

    构造列表

    使用格式:

    // 在已有列表前端增加元素
    元素::列表
    
    // 将元素 D 添加到新列表 a_list 中
    scala> val a_list = "D"::strList
    a_list: List[String] = List(D, A, B, C)
    
    // 生成一个新的列表 a_list
    scala> a_list
    res3: List[String] = List(D, A, B, C)
    
    // 原列表保持不变
    scala> strList
    res4: List[String] = List(A, B, C)
    

    Nil 空列表对象

    scala> val b = 1::2::3::Nil
    b: List[Int] = List(1, 2, 3)
    
    // 效果与  List(1, 2, 3) 等同
    

    4.3 集合

    集合的元素不重复,无序,以 哈希 方式来组织元素,包括:

    • 可变集合:scala.collection.mutable
    • 不可变集合:scala.collection.immutable,缺省情况下创建的是不可变集合,通常使用不可变集合

    不可变集合

    // 不能使用 val
    scala> var set1 = Set("Hadoop", "Scala")
    set1: scala.collection.immutable.Set[String] = Set(Hadoop, Scala)
    
    scala> set1 += "Spark"
    
    scala> set1
    res6: scala.collection.immutable.Set[String] = Set(Hadoop, Scala, Spark)
    
    scala> set1.contains("Scala")
    res7: Boolean = true
    

    可变集合

    // 必须先引入 scala.collection.mutable.Set  
    scala> import scala.collection.mutable.Set                  
    import scala.collection.mutable.Set                         
                                                                
    scala> val set2 = Set("A", "B")                             
    set2: scala.collection.mutable.Set[String] = Set(B, A)      
                                                                
    scala> set2 += "C"                                          
    res8: set2.type = Set(B, C, A)                              
    

    注意:对不可变集进行操作,会产生一个新的集合,原来的集合并不会发生变化。 而对可变集进行操作,改变的是该集合本身

    4.4 映射

    映射是一系列键值对的集合,类似于字典,键唯一,值不唯一,分为可变和不可变映射,同样地创建可变映射需要引入 scala.collection.mutable.Map

    不可变映射

    scala> val map1 = Map("name" -> "rose", "age" -> 18)
    map1: scala.collection.immutable.Map[String,Any] = Map(name -> rose, age -> 18)
    
    // 取值
    scala> map1("name")
    res10: Any = rose
    
    scala> println(map1("name"))
    rose
    
    // 判断是否包含某个键
    scala> map1.contains("age")
    res12: Boolean = true
    

    注意:不可变映射,是无法更新映射中的元素的,也无法增加新的元素。如果要更新映射的元素,就需要定义一个可变的映射

    可变映射

    scala> import scala.collection.mutable.Map
    import scala.collection.mutable.Map
    
    scala> val map2 = Map("name" -> "rose", "sex" -> "female")
    map2: scala.collection.mutable.Map[String,String] = Map(name -> rose, sex -> female)
    
    // 获取元素
    scala> map2("sex")
    res0: String = female
    
    // 添加新的元素,不是同一类型添加失败
    scala> map2("age") = 18
    <console>:14: error: type mismatch;
     found   : Int(18)
    *  required: String
           map2("age") = 18
                         ^
    
    scala> map2("age") = "18"
    
    scala> map2
    res3: scala.collection.mutable.Map[String,String] = Map(age -> 18, name -> rose, sex -> female)
    
    // 添加新的映射(可一次添加多个)
    scala> map2 += ("score" -> 98)
    <console>:14: error: type mismatch;
     found   : Int(98)
     required: String
           map2 += ("score" -> 98)
                               ^
    
    scala> map2 += ("score" -> "98")
    res5: map2.type = Map(age -> 18, name -> rose, sex -> female, score -> 98)
    
    // 重新赋值
    scala> map2("name") = "lila"
    
    scala> map2
    res7: scala.collection.mutable.Map[String,String] = Map(age -> 18, name -> lila, sex -> female, score -> 98)
    

    循环遍历映射

    scala> for ((k, v) <- map1) println(k, v)
    (name,rose)
    (age,18)
    
    
    scala> for (k <- map1.keys) println(k)
    name
    age
    
    scala> for (k <- map1.values) println(k)
    rose
    18
    

    4.5 数组

    数组是一种可变的、可索引的、元素具有相同类型的数据集合,可以通过显示指定类型或者隐式推断实例化一个数组,包含:

    • 定长数组:长度不变的数组
    • 变长数组:长度可变

    定长数组

    // 定义一个长度为 3 的 Int 类型数组
    scala> val intArr = new Array[Int](3)
    intArr: Array[Int] = Array(0, 0, 0)
    
    // 赋值
    scala> intArr(0) = 1
    
    scala> intArr(1) = 2
    
    scala> intArr(2) = 3
    
    scala> intArr
    res3: Array[Int] = Array(1, 2, 3)
    
    // 定义一个长度为 3 的 String 类型数组
    scala> val strArr = new Array[String](3)
    strArr: Array[String] = Array(null, null, null)
    
    scala> strArr(0) = "name"
    
    scala> strArr
    res5: Array[String] = Array(name, null, null)
    
    // 不指定数据类型
    scala> val intArr2 = Array(1, 2, 3)
    intArr2: Array[Int] = Array(1, 2, 3)
    

    多维数组

    // 定义个二维数组,三行四列
    scala> val a1 = Array.ofDim[Int](3, 4)                                                                        
    a1: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))                        
                                                                                                                  
    scala> a1(0)(0) = 1                                                                                           
                                                                                                                  
    scala> a1(0)(2) = 2                                                                                           
                                                                                                                  
    scala> a1(0)(1) = 3                                                                                           
                                                                                                                  
    scala> a1                                                                                                     
    res9: Array[Array[Int]] = Array(Array(1, 3, 2, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0))                      
    
    // 定义一个三维数组                                                                                              
    scala> val a2= Array.ofDim[String](3, 2, 4)                                                                   
    a2: Array[Array[Array[String]]] = Array(Array(Array(null, null, null, null), Array(null, null, null, null)), A
    rray(Array(null, null, null, null), Array(null, null, null, null)), Array(Array(null, null, null, null), Array
    (null, null, null, null)))                                                                                    
    

    可变长数组

    scala> import scala.collection.mutable.ArrayBuffer                                                 
    import scala.collection.mutable.ArrayBuffer                                                        
                                                                                                       
    scala> val a3 = ArrayBuffer(10, 20, 30)                                                            
    a3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 30)                            
                                                                                                       
    scala> a3 += 40                                                                                    
    res10: a3.type = ArrayBuffer(10, 20, 30, 40)                                                       
    
    // 在索引 2 的位置添加 60、80                                                                                           
    scala> a3.insert(2, 60, 80)                                                                        
                                                                                                       
    scala> a3                                                                                          
    res12: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 60, 80, 30, 40)             
    
    // 移除 40                                                                                                 
    scala> a3 -= 40                                                                                    
    res13: a3.type = ArrayBuffer(10, 20, 60, 80, 30)                                                   
                                                                                                       
    scala> val a4 = a3.remove(2)                                                                       
    a4: Int = 60                                                                                       
    
    // remove 不改变原数组                                                                                         
    scala> a3                                                                                          
    res14: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(10, 20, 80, 30)                     
    

    4.6 元组

    元组与列表不同之处在于,元组(索引从 1 开始)可以是不同数据类型,列表必须是相同数据类型:

    scala> val t1 = ("a", "b", "c", 1, 1.2)                                                      
    t1: (String, String, String, Int, Double) = (a,b,c,1,1.2)                                    
                                                                                                 
    scala> println(t1._1)                                                                        
    a                                                                                            
                                                                                                 
    scala> println(t1._2)                                                                        
    b                                                                                            
                                                                                
    scala> println(t1._3)                                                                        
    c                                                                                            
    

    4.7 迭代器

    Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,它有两个方法:

    • hasNext:检测是否有下一个元素
    • next():获取下一个元素
    scala> val iter1 = Iterator("A", "B", "C")
    iter1: Iterator[String] = non-empty iterator
    
    scala> while (iter1.hasNext) {println(iter1.next())}
    A
    B
    C
    
    scala> val iter2 = Iterator("A", "B", "C", "D")
    iter2: Iterator[String] = non-empty iterator
    
    // iter1 已经没有元素,所有没有输出
    scala> for (elem <- iter1) {println(elem)}
    
    scala> iter1
    res25: Iterator[String] = empty iterator
    
    scala> for (elem <- iter2) {println(elem)}
    A
    B
    C
    Dcala>
    

    grouped、sliding 方法

    • grouped:返回元素的增量分块,有点类似于切片
    • sliding:生成一个滑动元素的窗口
    scala> val xs = List(1, 2, 3, 4, 5)
    xs: List[Int] = List(1, 2, 3, 4, 5)
    
    scala> val a = xs grouped 3
    a: Iterator[List[Int]] = non-empty iterator
    
    // 一次获取三个元素
    scala> a.next()
    res0: List[Int] = List(1, 2, 3)
    
    // 如果后面元素不足 3 个,有几个就返回几个
    scala> a.next()
    res1: List[Int] = List(4, 5)
    
    // 一次获取三个元素,每调用一次 next(),就往后移动一位
    scala> val b = xs sliding 3
    b: Iterator[List[Int]] = non-empty iterator
    
    scala> b.next()
    res2: List[Int] = List(1, 2, 3)
    
    scala> b.next()
    res3: List[Int] = List(2, 3, 4)
    
    scala> b.next()
    res4: List[Int] = List(3, 4, 5)
    

    其他方法

    scala> val xs = List(1, 2, 3, 4, 5)
    xs.size		// 获取元素个数
    xs.length	// 获取迭代器长度
    xs.toString()	// 将迭代器转换为字符串
    
  • 相关阅读:
    HDOJ 1846 Brave Game
    并查集模板
    HDU 2102 A计划
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    POJ 1321 棋盘问题
    CF 999 C.Alphabetic Removals
    CF 999 B. Reversing Encryption
    string的基础用法
    51nod 1267 4个数和为0
  • 原文地址:https://www.cnblogs.com/midworld/p/15270048.html
Copyright © 2011-2022 走看看