• Scala(一)—— 基础


    一、基础

    REPL

    什么叫REPL?

    REPL是Read(读取)- Evaluate(求值)- Print(打印)-Loop(循环)。

    是Scala解释器的一个过程。

    输出

        println("Hello World")
    

    声明值与变量、常量

    1、变量用var表示,常量使用val表示

    2、变量类型声明

    
    var variableName : DateType [=Init Value]
    
    var x:String = "fonxian"
    
    

    3、多个变量声明

    var x,y = 100
    
    

    4、元组

    
    var x = ("x",18)
    
    

    常用类型

    scala不对基本数据类型包装数据类型做区分,这两种数据类型是由scala编译器完成的。

    在REPL中,输入3.,按tab键,会出现方法的提示

    3.toString()
    
        print(1.to(10))
        println()
        print(1 to 10)
    

    结果输出

    Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    

    调用函数和方法

    import scala.math._
    ## 输出16.0
    println(pow(2,4))
    

    apply方法

    两个语句等价

        // 输出o
        println("Hello"(4))
        println("Hello".apply(4))
    

    二、控制结构和函数

    五、访问限制符

    访问限制符有public、private、protected,默认为public

    被private修饰的成员只在包含该成员的类或对象中可见

    练习题

    题1:res变量是val还是var

    res是val

    题2:10 max 2 的含义是什么

    表示 10.max(2)

    元组

    元组是不同类型值的聚集

    //创建元组
    val t = (1,2.5,'holy','shit')
    //访问元组,访问第一个元素
    t._1
    

    函数

    try 表达式

    
    var result = try{
        Integer.parseInt("dog")
    }catch{
        case _ => 0
    }finally{
        println("excute")
    }
    
    

    match 表达式

    val code = 3
    var result = code match{
        case 1 => "one"
        case 2 => "two"
        case _ => "others"
    }
    
    

    求值策略

    • Call By Value
      • 对函数实参求值,且仅求值一次
    • Call By Name
      • 函数实参每次在函数体内被用到时都会求值
    
    def foo(x:Int,y: => Int):Int={
        x * x
    }
    
    def loop():Int = loop
    
    

    函数

    (1)匿名函数

    匿名函数定义格式 形参列表 => {函数体}

    (2)柯里化函数

    把具有多个参数的函数转换为一条函数链,每个节点上都是单一参数

    例子1:

    
    def add(x:Int)(y:Int) = x + y
    
    var add1 = add(1)_
    add1(5) 等同于 add(1)(5)
    
    def add2 = add(2)_
    add2(6)等同于add(2)(5)
    
    
    

    例子2

    
    def fun(f:Int => Int)(a:Int):Int={
    
        f(a)
        
    }
    
    fun(x=>x*x)(5) //等同于  f(x) =  x*x ;x = a;a=5;
    
    

    (3)尾递归

    覆盖当前记录,而不是在栈中创建新的函数

    
    @annotation.tailrec
    def fun(n:Int,m:Int):Int={
        if(n <= 0) m
        else fun(n-1,m*n)
    }
    
    @annotation.tailrec
    def fun1(n:Int,m:Int):Int={
        if(n == 1) m
        else fun(n-1,m+n)
    }
    
    

    例子1,计算f(x),a-b的求和

    该例子涉及到的知识点有函数柯里化、尾递归

    
    final def find(f:Int => Int)(a:Int)(b:Int):Int={
    
        @annotation.tailrec
        def loop(n:Int,acc:Int):Int={
    
          if(n > b){
            acc
          }else{
            loop(n+1,acc+f(n));
          }
    
        }
    
        loop(a,0)
      }
    
    

    一、控制语句

    var x = 40
    
    if(x == 40){
        println("greate")
    }
    
    

    二、循环

    (1) 一般循环

    
    while(a>1){
    
        if(a==2){
            break
        }
        a = a - 1
    }
    
    

    until x ,取到x以前的值

    to x,取到值为x的值

    
    for(i <- 0 until 10){
        println(i)
    }
    
    for(i <- 0 to 10){
        println(i)
    }
    
    

    (2) for循环集合

    for(x <- list){
        println(x)
    }
    
    

    (3) for过滤

    
    for(s<l;if s>0){
        println(s)
    }
    
    

    (4) 使用分号设置多个区间,相当于多层for循环

    
    for(a <- 1 to 3;b <- 1 to 3){
        println("a:"+a)
        println("b:"+b)
    }
    
    

    (5) for使用yield

    for循环的返回值作为一个变量存储

    var result = for{
        s <- l
        if(s > 0)
    }yield s
    

    一、List

    
    var x = List(1,2,3,4)
    //x:List[Int] = List(1, 2, 3, 4)
    
    var y = List("x","y","z")
    //y: List[String] = List(x, y, z)
    
    0 :: x
    //res6: List[Int] = List(0, 1, 2, 3, 4)
    
    x ::: y
    //List[Any] = List(1, 2, 3, 4, x, y, z)
    
    scala> "x"::"y"::"z"::Nil
    res9: List[String] = List(x, y, z)
    
    x.head //获取第一个元素
    
    x.tail //获取除第一个元素的其他元素
    
    x.isEmpty //判断该列表是否为空
    
    

    字符串转List

    
    var a = "HelloWorld,2018"
    //a: String = HelloWorld,2018
    
    a.toList
    //res0: List[Char] = List(H, e, l, l, o, W, o, r, l, d, ,, 2, 0, 1, 8)
    

    filter函数

    a.toList.filter(x => Character.isDigit(x))
    res1: List[Char] = List(2, 0, 1, 8)
    
    //另一种简写方式
    
    a.toList.filter(_.Character.isDigit(x))
    
    

    takeWhile函数

    
    a.toList.takeWhile(x => x!='d')
    res2: List[Char] = List(H, e, l, l, o, W, o, r, l)
    
    

    map函数

    
    var a = List(1,2,3,4)
    
    a.map(x => x % 2 == 0)
    a.map(_%2 == 0)
    
    var b = List(6,7,8)
    
    var p = List(a,b)
    
    a.map(_.filter(_%2 == 0))
    //res14: List[List[Int]] = List(List(2, 4), List(8))
    
    

    flatMap

    
    a.flatMap(_.filter(_%2 == 0))
    //res15: List[Int] = List(2, 4, 8)
    
    

    reduce函数

    
    a.reduce((x,y) => x+y) 
    
    //等价于
    
    a.reduce(_+_)
    
    

    foldLeft函数

    
    a.fold(0)((x,y) => x+y) 
    
    //等价于
    
    a.fold(0)(_+_)
    
    

    二、Tuple元组

    元组相当于数据库中的记录,可以放各种不同类型的值

    
    val a = (1,2,3,4)
    
    a._1 //访问元组中第一个元素
    
    a._2 //访问元组中第二个元素
    
    val b = (1,"fzj","math",95)
    
    

    例子1:返回一条记录,计算一个列表的元素个数、元素之和,元素的平方和

    
    val a = (1,2,3,4)
    
    def sum(list:List[Int]):(Int,Int,Int)={
        list.foldLeft(0,0,0)((x,y) => (x._1 + 1,x._2 + y,x._3 + y*y))
    }
    
    

    三、Set

    
    var x = Set(1,2,3,4)
    
    

    四、Map

    (1) 创建Map

    
    var  x = Map("one" -> "1","two" -> "2")
    
    var x:Map[String,String] = Map()
    

    (2) 添加key-value

    
    x += ("three" -> "three")
    
    

    (3) 合并

    使用 ++运算符 或 Map.++()方法来连接两个Map

    
    var colors = color1 ++ color2
    
    var colors = color1.++(color2)
    
    

    (4) 遍历

    
    val sites = Map("one"->"one","two"->"two","three"->"three")
    
    sites.keys.foreach{
        i =>
        println("key="+i+",value="+sites(i))
    }
    

    1、HelloWorld

    object HelloWorld{
    	def main(args:Array[String]):Unit={
    		println("hello,world")
    	}
    }
    

    编译并执行

    scalac HelloWorld.scala    
    scala HelloWorld.scala
    

    2、scala语法

    scala末尾的分号是可选的,区分大小写,类名的第一个字母要大写,方法名第一个字母要小写
    交互式编程

    1 + 1
    println("hello,world")
    

    3、函数

    def 方法名(参数名:类型):返回类型 = {
    
    }
    

    4、循环

    4.1 输出[1 - n]

    for(i <-  1 to n)
    

    4.2 输出[1,n)

    for(i <- 1 util n)
    

    4.3 遍历数组

    var a = Array("hello","world","fonxian")
        for(i <- a){
          println(i)
        }
    

    5、数组

    5.1 新建数组

    var a = new Array[Int](10)
    var b = Array("hello","world","fonxian")
    

    5.2 访问数组元素

    a(1)
    

    5.3 可变长度数组(等价于Java中ArrayList)

    新建

    var a = new ArrayBuffer[Int]()
    

    添加元素

    a += 1
    a += (1,2,3,4)
    a ++= ArrayBuffer(7,8,9)
    

    数组操作

    a.size
    a.remove(2) //去掉索引值为2的元素
    a.remove(2,3) //去掉以索引值为2的元素开始的3个元素
    a.trimEnd(n)  // 去掉尾部的n个元素
    a.trimStart(n) //去掉头部的n个元素
    a.insert(2,3) //索引值为2的位置插入一个元素
    
    

    数组的一些循环操作

    var result = for(elem <- a) yield 2*elem
    

    等价于

    for(elem <- a){
        elem = elem *2
    }
    
    var result = for(elem <- a if elem % 2 == 0) yield 8 * elem
    

    等价于

    for(elem <- a){
        if(elem % 2 == 0){
            elem = elem * 8
        }
    }
    

    6、映射

    6.1 不可变映射,键对应的值不可以被改变

    val scores = Map("feng" -> 100,"yun" -> 18)
    val fengScore = scores("feng")
    

    6.2 可变映射,键对应的值可以被改变

    val myScores = scala.collection.mutable.Map("feng"->100,"yun"->18)
    myScores("feng") = 1000
    

    6.3 创建空的映射

    val myScores1 = scala.collection.mutable.HashMap[String,Int]
    

    6.4 添加元素

    //添加元素 
    myScores1 += ((k,v))
    myScores1 += (("aaa",1),("bbb",2))
    

    6.5 获取映射元素的一种方法

    //获取映射元素的一种方法
    val omg = if(myScores1.contains("aaa")) myScores1("aaa") else 0
    

    6.6 获取映射元素的另一种方法

    //获取映射元素的另一种方法
    val omg = myScores1.getOrElse("aaa",0)
    

    6.7 删除一个映射元素

    //删除一个映射元素
    myScores1 -= "aaa"
    

    6.8 遍历映射元素的key

    //遍历映射元素的key
    myScores1.keySet
    

    6.9 遍历映射元素的value

    //遍历映射元素的value
    for(v <- myScores1.values){
        println(v)
    }
    

    6.10 map+reduce

    在经过map操作时,得到的是一个集合Vector(2,3,4,5),执行reduece操作时,得到5

    val my = Vector(1,2,3,4)
    my.map(n => n+1).reduce((a,b) => if(a>b) a else b)
    

    泛型

    定义一个泛型类

    class StackTest[A] {
      private var elements:List[A] = Nil
      def push(x : A): Unit ={
        elements = x::elements
      }
      def peek:A = elements.head
      def pop():A = {
        val currentTop = peek
        elements = elements.tail
        currentTop
      }
    }
    
    object StackUse {
    
      def main(args: Array[String]): Unit = {
    
        val stack = new StackTest[Int]
        stack.push(1)
        stack.push(2)
        println(stack.pop())
        println(stack.pop())
    
        val fruitStack = new StackTest[Fruit]
        val apple = new Apple
        val banana = new Banana
    
        fruitStack.push(apple)
        fruitStack.push(banana)
    
        println(fruitStack.pop())
        println(fruitStack.pop())
    
      }
    
    }
    
    class Fruit
    class Apple extends Fruit
    class Banana extends Fruit
    

    Scala出现的异常解决

    Error:(21, 37) could not find implicit value for evidence parameter of type org.apache.flink.api.common.typeinfo.TypeInformation[flink.SensorReading]
        val stream1 = env.fromCollection(list)
    
    

    原因是少引入了包,引入包问题解决

    import org.apache.flink.api.scala._
    

    参考文档

    《快学Scala》
    Scala官方文档

  • 相关阅读:
    mysql 设置自增主键id的起始值
    一文搞定MySQL的事务和隔离级别
    SpringBoot2.0整合Redis
    Redis Cluster搭建高可用Redis服务器集群
    为什么单线程的Redis这么快?
    Spring Boot使用AOP在控制台打印请求、响应信息
    Spring boot集成spring session实现session共享
    SpringBoot项目在IntelliJ IDEA中实现热部署
    Spring Boot入门-快速搭建web项目
    一篇文章搞定SpringMVC参数绑定
  • 原文地址:https://www.cnblogs.com/fonxian/p/8503426.html
Copyright © 2020-2023  润新知