• 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()	// 将迭代器转换为字符串
    
  • 相关阅读:
    List of yellow pages
    Bing Beats Google for the Best Way to X-Ray Search LinkedIn
    Search Engine Hacking – Manual and Automation
    42 Bing Search Engine Hacks
    Bing Advanced Search Tricks You Should Know
    Advanced search keywords
    10 Advanced Bing Search Tricks You Should Know
    python判断list中是否包含某个元素
    Python性能优化的20条建议
    CheatEngine查看PE header
  • 原文地址:https://www.cnblogs.com/midworld/p/15270048.html
Copyright © 2020-2023  润新知