Scala编程语言入门

Scala编程语言入门

一. Scala语言基础

1. Scala简介

  • Scala是一种多范式的编程语言(支持多种方式的编程),其设计的初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。它也能运行于CLDC配置的Java ME中。目前还有另一.NET平台的实现,不过该版本更新有些滞后。Scala的编译模型(独立编译,动态类加载)与Java和C#一样,所以Scala代码可以调用Java类库(对于.NET实现则可调用.NET类库)。Scala包括编译器和类库,以及BSD许可证发布。
  • 使用面向对象编程:封装、继承、多态
  • 使用函数式编程:最大的特点
  • 优点:代码非常简洁
  • 缺点:可读性太差,尤其是隐式类、隐式函数、隐式参数

2. Scala安装与配置

(1) Scala下载
(2) 解压后即安装成功
(3) 环境变量配置
  • 修改配置文件:
    • vi /etc/profile
  • 增加以下内容:
    • SCALA_HOME=/Users/apple/Documents/scala-2.11.8
    • export PATH=$PATH:$SCALA_HOME/bin
  • 声明环境变量:
    • source /etc/profile
(4) 命令行启动
  • scala
(5) 命令行退出
  • :quit

3. Scala的IDEA插件配置

(1) 插件下载
(2) 插件安装
  • 打开IDEA,点击Configure -> Plugins -> Install plugin from disk,找到本地的Scala插件包安装,完成后重启IDEA

4. Scala代码初体验

(1) 创建Maven
  • 创建的maven项目默认是不支持scala的,需要为项目添加scala的framework。
  • 在这里选择Scala后,在右边的Use library中配置安装目录即可,最后点击OK。
  • 在项目的目录结构中,创建scala文件夹,并标记为source。
(2) 初步测试
  • 在scala上点击右键创建scala class,注意选择成Object
  •   object FirstDemo {
        def main(args: Array[String]): Unit = {
          print("hello world")
        }
      }
    复制代码

5. Scala的数据类型和变量常量

(1) 数据类型
  • 注意:scala中所有的数据都是对象。 e.g.: 1在java中是int,在scala中,1就是一个对象。
  • 基本数据类型(Byte,Short,Int,Long,Float,Double):
    • Byte: 8位有符号数字,从-128 到 127
    • Short: 16位有符号数据,从-32768 到 32767
    • Int: 32位有符号数据
    • Long: 64位有符号数据
    • String: 字符串类型
    • Char: 字符
  • scala中字符串的插值操作(字符串的拼接)
    •   var s1 : String = "Hello "
      	  s1: String = "Hello "
      
      	  "My name is Tom and ${s1}"
      	  res1: String = My name is Tom and ${s1}
      
      	  插值操作时,需要加入 s 
      	  scala> s"My name is Tom and ${s1}"
      	  res2: String = "My name is Tom and Hello "
      复制代码
  • Unit类型和Nothing类型
    • <1>. Unit类型:
      • 即java中的void,没有返回值
        •   val f = ()
            f: Unit = ()
            
            返回值 Unit类型
            () 代表了一个函数,这个函数没有返回值
          复制代码
    • <2>. Nothing类型:
      • 在执行过程中,产生了异常Exception
  • 注意:在Scala中定义变量可以不指定类型,Scala会进行类型的自动推导。
(2) Scala变量的申明和使用
  • 使用val申明变量
    • e.g.: scala> val answer = 8 * 3 + 2
    • 可以在后续表达式中使用这些名称
    • val定义的值实际是一个常量
  • var申明其值可变的变量
  • 注意:可以不用显式指定变量的类型,Scala会进行自动的类型推导

6. Scala的函数和方法的使用

(1) scala内置函数(可直接使用)
- e.g.: 求两个数的最大值
- ```
  _ 就相当于java中的 * ,代表包内所有内容
	import scala.math._
	max(1,2)
	res4: Int = 2
	
	定义了一个变量 res4 ,接收了 max 函数的返回值。scala中支持类型的推导。
	```
复制代码
(2) scala自定义函数
  • 语法:
    • def 函数名称([参数名称:参数类型]*) : 返回值类型 = {
      		函数的实现
      	}
      	```
      复制代码
  • e.g.:
    • <1>. 求和:

      •    def sum(x:Int,y:Int):Int = x + y
               sum: (x: Int, y: Int)Int
        
             sum(1,2)
             res5: Int = 3
            ```
            
        复制代码
    • <2>. 求阶乘(5!= 5 * 4* 3 2 1):

      •      def myFactor(x:Int):Int = {
          	   if(x<=1)
          	   1
          	   else
          	   x*myFactor(x-1)
          	 }
              myFactor: (x: Int)Int
        
          myFactor(5)
          res6: Int = 120
        复制代码
        • 注意:没有return语句,函数的最后一个语句,就是函数的返回值
    • <3>. 求输入的年份是否是闰年 - 闰年定义: - 普通闰年:可以被4整除但是不能被100整除的年份 - 世纪闰年:可以被400整除的年份 - ``` scala> def isLeapYear(x:Int) = { if(( x%4 == 0 && x%100 != 0) || (x%400==0)) true else false } isLeapYear: (x: Int)Boolean

        isLeapYear(2019)
        res7: Boolean = false
      
        isLeapYear(2008)
        res8: Boolean = true
        ```
      复制代码
      • 注意:函数定义的时候,可以不写返回值,因为scala支持类型推导

7. Scala的条件表达式

  • Scala的if/else语法结构和Java或C++一样。
  • Scala中,if/else是表达式,有值,这个值就是跟在if或else之后的表达式的值。

8. Scala的循环

  • Scala拥有与Java和C++相同的while和do while循环
  • Scala中,可以使用for和foreach进行迭代
  • 使用for循环案例:
    • import util.control.Breaks._
      import scala.math._
      
      /**
        *
        * @ClassName: Demo1
        * @Description
        * @Author: YBCarry
        * @Date2019-05-07 08:15
        * @Version: V1.0
        *
        **/
      object Demo1 {
      
        def main(args: Array[String]): Unit = {
      
          /*
          * for 循环
          * 定义一个集合
          * */
      
          var list = List("Mary", "Tom", "Mike")
      
          println("--------for循环的第一种写法--------------")
          /*
          * <- 表示Scala中的generator,即:提取符  把list中的每一个元素,赋给s
          * */
          for (s <- list) println(s + " ")
      
          println("--------for循环的第二种写法--------------")
          //打印长度大于3的名字  加判断
          for {
            s <- list
            if (s.length > 3)
          } println(s)
      
          println("--------for循环的第三种写法--------------")
          //对第二种,进一步简化
          for (s <- list if s.length <= 3) println(s)
      
          println("--------for循环的第四种写法--------------")
          /*
          * 1、把list中所有元素,都变成大写
          * 2、返回一个新的集合
          * yield 记录每次迭代中的有关值,并逐一存入到新数组
          * */
          var newList = for {
            s <- list
            s1 = s.toUpperCase()
          } yield (s1)
          for (s <- newList) println(s)
      
          println("--------while循环--------------")
          //定义循环变量
          var i = 0
          while (i < list.length) {
            println(list(i))
            /*
              * 自增
              * 注意: scala中 没有 i++
              * */
            i += 1
          }
      
          println("--------do while循环--------------")
          //定义一个循环变量
          var j = 0
          do {
            println(list(j))
            j += 1
          } while (j < list.length)
      
          println("--------for each 循环--------------")
          /*
          * foreach(没有返回值) scala里面有 spark里面会用到
          * map循环(有返回值)
          *
          * foreach 说明
          * foreach 是list的一个方法
          * 把一个函数,传入了foreach —> 高阶函数(函数式编程)
          * */
          list.foreach(println)
      
      
          /** 循环应用实例 */
          /*
          * 1. 判断101-200之间有多少个素数
          *
          * 判定素数的方法:
          * x % 2 -- x % sqrt(根号) x
          * 当都不能被整除的时候,就是素数
          *
          * e.g.:
          * 16 sqrt(16)=4
          * 故循环除2 3 4
          * 验证能否被整除:16%2 == 0 ?
          *
          * 编程思路 —— 两层循环:
          *   第一层 101-200
          *     第二层 2 sqrt第一层
          *
          * */
      
          println("-----------1. 判断101-200之间有多少个素数-------------")
          println("-----------循环嵌套-------------")
          var count: Int = 0 //保存结果
          var index_outer = 0 //外层循环变量
          var index_inner = 0 //内层循环变量
      
          for (index_outer <- 101 until 200) {
      
            var b = false //标识是否能被整除
            index_inner = 2
            /*
            * scala中使用的是函数块的风格来解决breakcontinue的问题
            * 相比java的一个关键词搞定的写法有点复杂
            * 但符合函数式编程的风格
            * */
            breakable {
              while (index_inner <= sqrt(index_outer)) {
                if (index_outer % index_inner == 0) {
                  b = true
                  break
                }
                index_inner += 1
              }
            }
            if (!b) count += 1
          }
          println("素数个数为:" + count)
      
      
          /*
          *1. 冒泡排序
          *
          * 算法分析:
          * 1、比较相邻的元素。如果第一个比第二个大,就交换
          * 2、对每一对相邻元素都做上述工作,循环完第一次后,最后的元素,就是最大的元素
          * 3、针对剩下的元素,重复上面工作(除了最后一个元素)
          *
          * 程序分析:
          * 1、两层循环
          * 2、外层循环控制比较的次数
          * 3、内层循环控制到达的位置,就是 结束比较 的位置
          * */
          println("-----------2. 冒泡排序-------------")
          var a = Array(12, 3, 6, 2, 4, 7, 9, 5, 30, 1)  //初始数据
          println("-----------排序前-------------")
          a.foreach(println)
      
          for (i <- 0 until a.length - 1) {
            for (j <- 0 until a.length - i - 1) {
              if (a(j) > a(j + 1)) {
                // 判断相邻元素大小
                var tmp = a(j)
                a(j) = a(j + 1)
                a(j + 1) = tmp
              }
            }
          }
      
          println("-----------排序后-------------")
          a.foreach(println)
        }
      
      }
      
      复制代码

9. Scala函数的参数

(1) 函数参数的求值策略
  • <1>. Call By Value:
    • 对函数实参求值,且仅求一次
  • <2>. Call By Name:
    • 函数实参每次在函数体内被用到时都会求值
  • e.g.1:
    •    scala> def test1(x:Int,y:Int) = x + x
      		test1: (x: Int, y: Int)Int
      
      		scala> test1(3+4,8)
      		res9: Int = 14
      
      		scala> def test2(x : => Int,y : => Int) = x+x
      		test2: (x: => Int, y: => Int)Int
      
      		scala> test2(3+4,8)
      		res10: Int = 14
      		
      		执行过程对比:
      		test1 ---> test1(3+4,8)  ---> test1(7,8)  ---> 7+7 ---> 14
      		test2 ---> test2(3+4,8)  ---> (3+4) + (3+4)  ---> 14
      复制代码
  • e.g.2:
    •   def bar(x:Int,y : => Int) : Int = 1
      		x 是 value y 是 name
      		
      		定义一个死循环:
      		def loop() : Int = loop
      		
      		调用bar函数的时候:
      		1、bar(1,loop)
      		2、bar(loop,1)
      		
      		问题:哪个方式会产生死循环?
      		
      		scala> def bar(x:Int,y : => Int) : Int = 1
      		bar: (x: Int, y: => Int)Int
      
      		scala> def loop() : Int = loop
      		loop: ()Int
      
      		scala> bar(1,loop)
      		res11: Int = 1
      
      		scala> bar(loop,1)
      		
      		解析:
      		1、虽然 y 是 name, 每次调用的时候会被求值。但是,函数体内,没有调用到y。
      		2、x 是 value,对函数参数求值,并且只求一次。虽然后面没有用到x,但求值时产生了死循环。
      复制代码
(2) Scala中的函数参数
  • <1>. 默认参数
    • 当没有给参数值赋值的时候,就会使用默认值。
  • <2>. 代名参数
    • 当有多个默认参数的时候,通过代名参数确定给哪个函数参数赋值。
  • <3>. 可变参数
    • 类似于java中的可变参数,即参数数量不固定。

10. Scala的Lazy值(懒值)

  • 当val被申明为lazy时,它的初始化将被推迟,直到我们首次对它取值。

11. 异常的处理

  • Scala异常的工作机制和Java或者C++一样。直接使用throw关键字抛出异常。

12. Scala中的数组

(1) Scala数组的类型:
  • <1>. 定长数组:
    • 使用关键字Array
    • val a = new Array[Int](10)
      (10) 就是数组的长度
      
      初始化赋给默认值
      	Array[String] = Array("Tom","Lily")
      复制代码
    • 注意:不能往数组中添加不同类型的元素
  • <2>. 变长数组:
    • 使用关键字ArrayBuffer
    • import scala.collection.mutable._
      val b = ArrayBuffer[Int]()
      
      增加元素:
      b += 1
      	b.type = ArrayBuffer(1)
      	b += 2
      	b.type = ArrayBuffer(1, 2)
      	b += (1,2,3,4)
      	b.type = ArrayBuffer(1, 2, 1, 2, 3, 4)
      	
      	删除最后两个元素:
      	b.trimEnd(2)
      scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2)
      
      遍历数组:
      forfor(s <- a ) println(s)
      foreach:a.foreach(println)
      
      最值:
      b.max
      b.min
      
      排序:
      降序:b.sortWith(_>_)
      升序:b.sortWith(_<_)
      复制代码
(2) 多维数组
  • 通过数组的数组来实现
  •   创建X行Y列的数组
      var c = Array.ofDim[Int](X,Y)
      
      为x行y列赋值为n
      c(x - 1)(y - 1) = n
      
      定义一个二维数组,其中每个元素是一个一维数组,并且长度不固定
      var d = new Array[Array[Int]](10)
      for(i <- 0 until d.length){
      		   d(i) = new Array[Int](i+1)
      		   }
      		 
      二维数组,如果使用 Array[Array[Int]](10) 声明时:
      	1、首先指定的是外层数据的长度
      	2、初始化内层数组的时候,再指定内层数组的长度
    复制代码

13. 映射

  • 映射就是Map集合,由一个(key,value)对组成。
  • val scores = Map(“Alice” -> 10,”Bob” -> 3,”Cindy” -> 8)
    复制代码
  • 映射的类型
    • 可变Map:scala.collection.mutable
    • 可变Map:scala.collection.immutable

转载于:https://juejin.im/post/5cd01d1be51d456e40377370

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值