zoukankan      html  css  js  c++  java
  • Scala基础

    Scala基础

    1、介绍

    Scala是spark和kafka采用的编程语言,本质上是对java语言进行脚本化处理,使得开发效率更高。Scala的代码编写起来非常简洁,但并不简单,主要是很多语法比较诡异,对于刚刚接触到scala的人员来讲,往往有些摸不到头脑。

    2、scala使用

    打开scala的shell命令行窗口,输入1 + 1,可以直接进行求值运算。scala shell采用REPL方式进行交互,即read->evalute->print->loop。进入如下环境,运行效果如下图所示:

    cmd>scala.bat
    scala> 1 + 1
    

    1538193648630

    2.1 查看帮助

    $scala>:help
    

    1538193747272

    2.2 退出

    $scala>:quit
    

    2.3 常量和变量

    scala的量分为常量和变量,var是变量,可以重新赋值,val是常量,不可以重新复制。

    // 变量
    val x =10
    // 错误,不能重新赋值
    x = 20
    
    var x = 10
    // 正确
    x = 20
    

    2.4 类型推断与自动补全

    val x = 100
    val x:Int = 100
    // tab键自动提示
    x.<tab>
    

    2.5 定义函数

    递归函数必须显式定义函数,因为无法进行类型推荐。

    // 参数必须定义类型,返回值可以不写,自动推断出来
    def add(a:Int,b:Int) = {
        a + b
    }
    
    // 显式定义返回值类型
    def add(a:Int,b:Int):Int = {
        a + b
    }
    
    // 递归实现阶乘
    def frac(n:Int):Int = {
    	if(n == 1) 1 else n * frac(n - 1)
    }
    

    2.6 to和until

    to和until都可以定义Range集合,to是闭区间,until是半闭半开区间。

    // 1 .. 10
    1 to 10
    1.to(10)
    
    // 1 .. 9
    1 until 10
    1.until(10)
    

    2.7 字符串

    // 取交集,lo
    "hello".intersect("world")
    

    2.8 BigInt

    var b = BigInt(999999999)
    b * b * b * b
    

    2.9 ++/--

    scala没有++或--操作,可以使用+=或-=,这些也都是方法。

    var x = 1 
    // x ++ 
    x += 1
    x.+=(1)
    
    // x --
    x -=1 
    x.-=(1)
    

    2.10 sqrt与pow

    开方函数和幂函数都在math包下,因此需要导入才能使用:

    import scala.math._
    // 4开方=2.0
    sqrt(4)
    // 2的立方=8
    pow(2,3)
    

    2.11 表达式的值

    scala的每个表达式或者代码块都有值,最后一行语句的值就是表达式的值。

    val x = 2
    // y = 1
    val y = if (x < 1) -1 else 1 
    

    2.12 apply方法

    scala为很多类提供了apply方法,可以方便进行各种对象的创建和元素的获取,apply方法名成通常可以省略,因此会让方法调用显得有些奇怪。

    // 省略apply方法名
    val arr = Array[Int](1,2,3)
    val arr = Array[Int].apply(1,2,3) ;
    
    // 省略了apply方法
    "hello"(0)
    "hello".apply(0)
    

    2.13 粘贴模式

    在scala shell可以使用粘贴模式来贴入大量代码:

    # 进入粘贴模式的命令
    $scala>:paste
    
    # ctrl + d退出粘贴模式
    

    2.14 读取控制台输入

    // 字符串为控制台提示符
    val name = readLine("请输入用户名:") ;
    println(name) ;
    

    运行结果如图:

    1538203922670

    2.15 循环

    2.15.1 while

    while循环同java相似,都是用boolean类型表示进行控制。

    • 输出1~10

      var n = 1
      while(n < 11){
      	println(n)
          n += 1
      }
      
    • 输出99表格

      var row = 1
      while( row <= 9 ){
      	var col = 1 
          while( col <= 9){
          	printf("%dx%d=%d	" ,col,row , (col * row))
          }
          println()
      }
      
    2.15.2 for
    • 输出1~10

      for(i <- 1 to 10){
      	println(i)
      }
      
    • 输出99表格

      for(r <- 1 to 10){
          for(c <- 1 to r){
              printf("%dx%d=%d	" ,c,r , (c * r))
          }
          println()
      }
      

      运行结果如下:

      1538204862072

    • 带守卫条件的循环

      for(i <- 1 to 3 ; j <- 4 to 6 if j != 5){
        printf("%d : %d
      " , i , j )
      }
      

      如果j不等5的条件下,和i进行组合计算:

      1538212280072

    2.16 break

    scala没有break语句,需要导入特定的函数来执行:

    // 导入break函数
    import scala.util.control.Breaks.break
    
    for(i <- 1 to 10){
      if(i % 3 == 0){
        break 
      }
    }
    

    2.17 yield产生新集合

    // 每个元素 * 2,组成新集合
    for(i <- 1 to 5) yield i * 2
    

    执行结果如下:

    1538212654302

    2.18 函数

    • 定义函数

      // 递归函数必须显式定义返回值类型
      def fac(n:Int) : Int = {
      	var result = 0 
          for(i <- (1 to n)){
          	result *= i
          }
          //最后一条语句是返回值
          result
      }
      
    • 参数默认值和带名参数

      // 定义修饰串函数
      def decorate(prefix:String="{{{" , str:String  , suffix:String="}}}") = {
      	prefix + str + suffix 
      }
      //调用函数
      decorate("<<<" , "hello" , ">>>")
      // 输出结果
      "<<<hello>>>"
      // 使用带名参数向特定参数传值
      decorate(str="world" , suffix="}}}")
      
    • 变长参数

      变长参数等价于java中的可变参数,即参数的类型个数可以不固定。

      // 定义可变参数
      def add(x:Int*) = {
          var sum = 0 
          for(i <- x){
          	sum += i 
          }
          sum
      }
      
      // 传递多个参数
      add(1,2,3)
      
      // 使用_*转换成数字序列
      add(1 to 10 :_*)
      
    • 过程

      scala中将不带“=”的函数称之为过程,本质上和函数没有区别。

      // 没有=号
      def sayHi() {
          println("hello world!")
      }
      

    2.19 lazy

    lazy是延迟计算,即表达式不会立即求值,而是使用lazy字样作为占位符,等真正用到的时候再进行计算。spark的广播变量中使用该中方式进行的实现。

    // lazy变量,不会出错
    lazy var x = 1 / 0
    
    // 出错
    x 
    

    2.20 定义数组

    • 一维数组

      # 定义一个一维数组,长度为5个元素。
      val arr = new Array[Int](5)
      
      # 定义一个一维数组,内部调用apply方法
      var arr = Array[Int](5)
      var arr = Array[Int](1,2,3,4,5)
      
    • 二维数组

      // 定义二维数组
      var arrr = new Array[Array[Int]](3)
      // 赋值
      arrr[0] = Array[Int](1,2,3)
      
      # 三行四列数组
      val arr = Array.ofDim[Int](3,4)
      # 第一行第二列为2
      arr(0)(1) = 2
      

    2.21 ArrayBuffer

    数组缓冲区是可变数组,位于scala.collection.mutable包下,使用时需要进行导入。scala使用符号定义的方法有一定规律性:

      当个符号的方法通常意味着操纵一个元素,如:

      val arr = ArrayBuffer[Int](1,2,3)
      arr.+(4)
      
    • ++

      两个以上符号命名的方法意味着操纵的是集合元素,如:

      arr.++(5 to 8)
      
    • +=

      带有“=”号的方法意味着对自身的修改,如:

      // 改变自身的内容
      arr.+=(4)
      
    • 常用方法

      buf.trimEnd(3)				// 删除最后的三个元素
      buf.insert(0,1,2,3)			// 在0位置插入1,2,3序列
      buf.toArray()				// 转换成数组
      buf.reverse()				// 倒序
      buf.sum()					// 求和
      buf.max()					// 最大值
      buf.mkString(",")			// 对元素拼接成串
      buf.mkString("{",",","}")	// 对元素拼接成串
      

    2.22 java与scala集合互操作

    java集合可以和scala进行相互无缝调用,需要导入隐式转换包才可以。代码如下:

    /* 自动将scala buffer转换成java list */
    val list:java.util.List[String] = new java.util.ArrayList[String]()
    list.add("hello")
    list.add("world")
    def mybuf(buf:scala.collection.mutable.Buffer[String]) = println(buf.size())
    import scala.collection.JavaConversions.asScalaBuffer
    mybuf(list)
    
    /* 自动将scala buffer转换成java list */
    val buf = ArrayBuffer[String]("how" , "are" , "you")
    def mylist(list:java.util.List[String]) = println(list.size())
    import scala.collection.JavaConversions.bufferAsJavaList
    mylist(buf)
    

    3、map操作

    val t = (1 , "tomas" , 12)	// 元组
    val t = (1 , "tomas")		// 对偶,对偶是特殊的元组,只有两个元素。
    val t = 1 -> "tomas"		// 对偶
    
    
    val map = Map(1->"tom" , 2->"tomas" , 3->"tomasLee")	// 构造map
    val map = Map((1,"tom"),(2,"tomas"),(3,"tomasLee"))		// 构造map
    
    map(1)	// 指定key,访问value
    map(2)	//
    
    // 迭代key-value
    for((k,v) <- map){
    	println(k + " : " + v)
    }
    
    // 迭代key
    for(k <- map.keys){
        ...
    }
    
    // 迭代values
    for(v <- map.values){
    	...
    }
    
  • 相关阅读:
    AcWing:141. 周期(KMP)
    暑假集训
    AcWing:112. 雷达设备(贪心 + 笛卡尔坐标系化区间)
    AcWing:111. 畜栏预定(贪心 + 小根堆)
    20200207总结
    Miku and Generals(二分图染色+可行性dp)
    20200205总结
    Coding Contest(最小费用最大流)
    Wannafly-Winter-Camp day5总结
    Wannafly-Winter-Camp day4总结
  • 原文地址:https://www.cnblogs.com/xupccc/p/9842974.html
Copyright © 2011-2022 走看看