zoukankan      html  css  js  c++  java
  • SCALA-基础知识学习(一)

    概述

    本人开始学习scala的时候,是在使用和开发spark程序的时候,在此为了整理、记录和分享scala的基础知识,我写这篇关于scala的基础知识,希望与广大读者共同学习沟通进步。如果有些代码比较简单,我就略去过分的文字说明。

    SCALA常与句式的使用

    变量的定义:在scala中变量有两个关键字:val和var,val:是不可变的,即不可以在此给其赋值,类似于java中被final修饰的常量,var:是可变的,即可以再次赋值,声明变量的通用格式

       关键字   变量名 :变量的类型=变量值

    val name: String = "wwss"
        var name2: String = "tom"
        val age: Int = 500
    
        //声明变量可以将变量类型省略,scala会根据变量的值自动推断也出变量的类型
        val sex = "男"
    
        //也可以使用Any作为变量的类型,Any类似于java中的Object
        val color: Any = "red"
    
        //可以一次声明多个变量
        val name1, name5, name3, name4: String = "旺财"
    

    for循环:和java类似,

        //使用to方法会产生一个连续不断的区间范围,[0,10]左右两边都包含
        for (i <- 0 to 10)
          println(i)
    
        //使用until方法会产生一个连续不断的区间范围,但是不包含最后一个数字[0,10)
        for (a <- 0 until (10))
          println(a)
    
        //遍历字符串
        for (s <- "abcdfeg")
          println(s)
    
        //多重for循环
        for (i <- 1 to 9; j <- 1 to 9) {
          if (j == 9) {
            println(i + "*" + j + "=" + i * j + "   ")
          } else {
            print(i + "*" + j + "=" + i * j)
          }
        }
    
        //带有if守卫条件的for循环
        for (i <- 0 to 10 if (i % 2 == 0))
          println(i)
    
        //推导式for循环
        val arr = for (i <- 0 to 5) yield i * 2
        for (a <- arr) {
          println(a)
        }
    
        //遍历数组
        val arr2 = Array(1, true, "string")
        for (a <- arr2) {
          println(a)
        }
    
        //中断跳出for循环
        breakable({
          for (i <- 0 to 10) {
            println(i)
            if (i >= 5) {
              break()
            }
          }
        })
    

    if 判断语句:也和java类似

    //在scala中不需要添加分号作为语句块的结束符
        val num = 20
    
        //在scala中if else语句是有返回值的,
        //返回值就是最后一条语句的返回值
        if (num > 20) "zs" else "ls"
        //因为if else 语句是有返回值的,所以可以直接将
        //if else语句赋值给一个变量
    
        //在scala中无论是方法或函数以及条件判断等都只要是有返回值都不需要加return关键字
        val name = if (num > 20) "zs" else "ls"
        println(name)
    
        //如果在if else语句中返回的值类型不一样,scala会自动推断出两者
        //的公共类型,作为变量的类型,any
        val name2 = if (num == 20) "zs" else 100
        println(name2)
    
        //如果if else语句缺省了else语句块,那么其实默认是没有返回值Unit,Unit用"()"表示,
        //类似于java中void
        val name3 = if (num > 20) "zs"
        //和上面的等价
        val name4 = if (num > 20) "zs" else ()
        println(name3)
    

    打印输入输出的格式:

    val name = StdIn.readLine("请输入用户名:
    ")
        val password = StdIn.readLine("请输入密码:
    ")
        if(name.equals("admin") && password.equals("admin")) {
          printf("欢迎您%s登记",name)
        } else {
          println("你输入的用户名或者密码错误,系统自动退出")
        }
    

    while语句格式:

     var num = 0;
        do {
          println(num)
          num += 1
        } while (num <= 5)
    
        //使用break()方法跳出while循环
        var num2 = 0
        breakable({
          while (true) {
            num2 += 1
            if (num2 > 5) {
              break()
            }
            println(num2)
          }
        })
    
        var flag = true
        var num3 = 0
        while (flag) {
          num3 += 1
          if (num3 > 10) {
            flag = false
          }
          println(num3)
        }
    

    SCALA方法和函数的使用

     在scala比较正规的解释是:

    Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

    Scala 中的方法跟 Java 的类似,方法是组成类的一部分。

    Scala 中的函数则是一个完整的对象,Scala 中的函数其实就是继承了 Trait 的类的对象。

    定义函数的关键字是:val

    定义函数的通用格式:val  函数名=(参数列表)={函数体}

     //通用的定义格式
      val f1 = (x: Int, y: Int) => {
        x + y
      }
    
      //先定义函数的参数列表类型,具体的函数参数在函数体中定义
      val f2: (Int, Int, Int) => Int = {
        (x, y, z) => {
          x + y + z
        }
      }
    

    定义方法的关键字是:def

    定义方法的通用格式:关键字  方法名(参数列表) :方法的返回值类型={方法体}

    //方法的返回值不需要使用return关键字,同时方法的最后一条语句的返回
      //值作为整个方法的返回值,
      //注意:如果一个方法 的返回值,那么方法 的最后一条语句的返回值一定要和方法 的返回值类型保持一致
      def m1(x: Int, y: Int): Int = {
        var a = 1
        a += 2
        x + y
      }
    
      //可以省略掉方法的返回值类型,scala会自动根据最后一条语句的返回值推断出方法的返回值类型
      def m2(x: Int, y: Int) = {
        x + y
      }
    
      //如果方法没有返回值,可以使用Unit来表示标注,表现为“()”,类似于java中的void
      def m3(x: Int, y: Int): Unit = {
        x + y
      }
    
      //也是没有返回值的方法,在参数列表括号后面直接添加方法体括号,我们称这种方法为过程
      def m3_3(x: Int, y: Int) {
        println(x + y)
      }
    
      //先定义方法参数列表类型,具体的参数名称在方法体中
      def m4: (Int, Int, Int) => Int = {
        (x, y, z) => {
          x + y + z
        }
      }
    
      //柯理化
      def m5(x: Int)(y: Int) = {
        x + y
      }
    
      //柯理化
      def m6(x: Int) = (y: Int) => {
        x + y
      }
    
      //如果定义一个方法,后面方法名称后面的参数列表为空,那么在调用的时候可以加括号,也可以不加括号
      def m7() = {
        println("hello world")
      }
    
      //如果定义一个方法,方法没有参数列表,那么在调用的时候也不能加括号,否则编译不通过
      def m8 = {
        println("hello scala")
      }
    
    
      //递归方法要求我们必须写明方法的返回值类型,不能省略掉,否则报错
      def m9(num: Int): Int = {
        if (num <= 0) 0 else m9(num - 1)
      }
    
      //当参数个数不固定时,那么这时候可以将参数定义为可变参数,可变参数要求是方法的最后一个参数
      def m10(name: String, nums: Int*): Unit = {
        var sum = 0
        for (num <- nums) {
          sum += num
        }
        println(name + "=" + sum)
      }
    
      //在scala中,有时我们调用某些方法时,不希望给出参数的具体值,而希望使用参数自身默认的值
      //此时就定义方法时使用默认参数
      //在调用方法的时候,赋值是从左向右依次赋值,所以说需要把没有默认值的放在最前面
      def m11(age: Int, name: String = "旺财", sex: String = "男") = {
        println(name + "=" + age + "=" + sex)
      }
    

    函数和方法的区别:

    1,方法中的参数列表是可选的,即:参数列表可以没有,也可以为空。比如:方法可以这样写  def me() = 10 ; def me = 10 ;

    但是对于函数来说,参数列表是强制的,即:参数列表可以为空,但不能没有。比如:val f=()=>10这里的括号不能省略。

    2,参数传递,函数是可以作为参数传递,函数名只是代表函数自身;方法不能作为参数传递,用的方法名的地方意味这调用,那为什么在需要函数出现的地方我们可以提供一个方法,在scala中很多高级函数,如map(),filter()等,都是要求提供一个函数作为参数。但是为什么我们可以提供一个方法呢,比如这样:val myList = List(3,56,1,4,72)。

    这是因为,如果期望出现函数的地方我们提供了一个方法的话,该方法就会自动被转换成函数。

    3,方法可以作为一个表达式的一部分出现(调用函数并传参),但是方法(带参方法)不能作为最终的表达式,但是函数可以作为最终的表达式出现。

    scala> //定义一个方法
    
    scala> def m(x:Int) = 2*x
    m: (x: Int)Int
    
    scala> //定义一个函数
    
    scala> val f = (x:Int) => 2*x
    f: Int => Int = <function1>
    
    scala> //方法不能作为最终表达式出现
    
    scala> m
    <console>:9: error: missing arguments for method m;
    follow this method with `_‘ if you want to treat it as a partially applied function
                  m
                  ^
    
    scala> //函数可以作为最终表达式出现
    
    scala> f
    res9: Int => Int = <function1>
    

    方法转换函数的方法:

    在scala中方法可以转换为函数,有两种转换方法,

    1,下划线:方法名 _

    2,scala会隐式转换,不需要手动转换。

    def m1(x: Int, y: Int) = {
        x + y
      }
    
      //
      /**
        * m2接收三个参数,
        *
        * @param f 它是一个函数,接收两个参数,返回值是Int类型,在传入这个参数时,
        *          传入进来的参数必须符合函数的签名
        * @param y 普通参数
        * @param x 普通参数
        * @return
        */
      def m2(f: (Int, Int) => Int, y: Int, x: Int) = {
        f(x, y)
      }
    
      def main(args: Array[String]): Unit = {
        //通过下划线将方法转换成函数
        val f1 = m1 _
        println(f1)
    
        //scala会自动进行转换
        val v2 = m2(m1, 1, 2)
        println(v2)
    
        val foreachFunction = (x: Int) => {
          println(x)
        }
    
        val arr = Array(1, 2, 3, 4, 5)
        arr.foreach(foreachFunction)
    
        arr.foreach((x: Int) => {
          println(x)
        })
    
        arr.foreach((x) => println(x))
    
        arr.foreach(println(_))
    
        println("********************")
        val filterFunction = (x: Int) => {
          x > 3
        }
        arr.filter(filterFunction).foreach((x: Int) => println(x))
    
      }
    

    SCALA常用数据结构

    数组 Array

    在scala 中数组分为不可变长数组(在immutable包下)和可变长数组(在mutable包下),不可变是指长度不可变,但是数组中角标元素的值是可变的,可变长数组是指长度和角标对应的元素的值都是可变的。

    /**
          * 不可变数组(一旦初  始化了,数组的长度是不可变的)
          */
        val arr = Array[Int](1, 2, 3, 4, 5)
    
        //如果一个数组中,有不同类型的元素,那么这个数组的类型是这些元素的公共类型Any
        val arr2: Array[Any] = Array("true", 1, true, "aaa")
    
        //创建一个数组,给数组初始化了长度为5,每个角标的初始值和泛型的初始值一致,也就是0
        val arr3 = new Array[Int](5)
        //创建一个数组,数组的长度是1,这个元素的值是5
        val arr4 = Array(5)
    
        //++运算符是将两个数组添加到新的数组中去,原来的数组并没有改变,只是形成了一个新的数组
        val arr5 = arr ++ arr4
    
    
        /**
          * 可变长数组
          */
        val buffer1 = ArrayBuffer[Int]()
        //如果是+=符号,那么后面只能跟单个元素
        buffer1 += 1
        buffer1 += 2
        //++=后面不能添加单个元素,只能添加数组集合
        buffer1 ++= Array(7, 8, 9)
        buffer1 ++= ArrayBuffer(1, 2, 3, 4, 5, 6)
        //这种添加方式是错误,
        //buffer1(12) = 10   //这种方式是修改角标元素的值,不是添加值
    
        buffer1.append(10, 11, 12)
    
        buffer1 -= 1
        buffer1 -= 2
        buffer1 --= Array(1, 2, 3, 4)
    
        //移除下标为5的对应的元素
        buffer1.remove(5)
        //从指定角标开始,移除指定个数的元素
        buffer1.remove(1, 2)
    
        println(buffer1)
    
    
        /**
          * 数组的常用方法
          */
        val array = Array(1, 2, 3, 4, 5)
    
        //最大值
        println(array.max)
        //最小值
        println(array.min)
        //mkString 拼接
        println(array.mkString)
    
        println(array.mkString(","))
    
        println(array.mkString("[", ",", "]"))
    
        //reverse相当于将数组反转
        println(array.reverse.toBuffer)
    
    
    
    
        /**
          * 数组的转换操作
          */
        val intArr = Array(1, 2, 3, 4, 5, 6)
    
        intArr
          .map((x: Int) => x * 2)
          .sortBy((x: Int) => x) //从小到大排序,即升序
          .reverse //将数组反转
          .foreach((x: Int) => println(x))
    
        println("************")
        intArr.map(_ * 2).sortBy(x => x).reverse.foreach(println(_))
    
        val strArr = Array("hello you", "hello me")
    
        strArr
          //Array(Array("hello","you"),Array("hello","me"))-->Array(hello,you,hello,me)
          .map(x => {
          val fields = x.split(" ")
          fields
        })
          //Array(hello,you,hello,me)
          .flatten
          .foreach(println(_))
    
        println("***************")
        strArr.flatMap((x: String) => x.split(" ")).foreach(println(_))
    
      }
    

    序列

    序列分为可变长序列和不可变长的,序列就是List,底层是链表结构,特点:插入有序,可重复,增加和移除元素很快,查询慢,不可变长序列:List。 可变长序列:ListBuffer

    /**
          * 不可变长序列List,长度不可变,角标元素也不可变
          */
        val list0 = List(1, 2, 3, 4, 5)
    
        //++并没有改变原有的list,只是将两个list序列进行合并形成一个新的list
        val list1 = list0 ++ List(6, 7, 8, 9)
        println(list1.toBuffer)
        println(list0.toBuffer)
    
        println("#####################")
    
        /**
          * 定义可变长度序列
          */
        val lb0 = ListBuffer(1, 2)
        //+=或-=后面只能跟一个单个的元素
        lb0 += 3
        lb0 -= 3
        //++=或--=后面只能跟一个序列list或者listbuffer
        lb0 ++= List(4, 5, 6)
        lb0 --= List(4, 5)
        lb0 ++= ListBuffer(8, 9, 10)
        lb0.append(11, 12)
    
        //移除指定角标的元素
        lb0.remove(0)
        //从指定角标开始,移除指定个数的元素
        lb0.remove(1, 2)
    
        println(lb0)
    
    
        println("****************ccccc************")
        /**
          * 给list头部添加元素
          */
        val list01 = List(4, 5, 6);
        //注意,这里并不是将元素添加到list01里面,而是将list01和后面的元素(1,2,3)进行合并 ,然后形成一个新的list
        //newList,需要注意的是后面的(1,2,3)是作为一个整体和list01进行合并
        var newList = list01.::(1, 2, 3)
        println(newList)
        println(list01)
        newList = list01.+:(1, 2, 3)
        println(newList)
    
        newList = (1, 2, 3) :: list0
        println(newList)
    
        newList = (1, 2, 3) +: list01
        println(newList)
    
        //这里是将1,2,3进行拆分开同list01进行合并
        newList = List(1, 2, 3) ++ list01
        println(newList)
    
        println("$$$$$$$$$$$$$$$$$$$$$$")
    
        /**
          * 给list尾部添加元素
          */
        val list02 = List(4, 5, 6)
        //这里也是将(7,8,9)作为整体同list02进行合并 添加到尾部,形成一个新的list
        var newList02 = list02.:+(7, 8, 9)
        println(newList02)
    
        //将7,8,9进行拆分同list02进行合并插入到list02后面去,形成一个新的list,原来的list并没有改变
        newList02 = list02 ++ List(7, 8, 9)
        println(newList02)
    
    
        /**
          * 序列的常用操作方法
          */
        val lt = List(1, 2, 3, 4, 5)
        //求和
        println(lt.sum)
        //最大值
        println(lt.max)
        //最小值
        println(lt.min)
        //第一人元素
        println(lt.head)
        //最后一个元素
        println(lt.last)
        //反转序列形成一个新的list,原来的list不会被改变
        println(lt.reverse)
        //拼接
        println(lt.mkString)
        println(lt.mkString(","))
        println(lt.mkString("[", ",", "]"))
    
    
        /**
          * 序列的转换操作
          */
        val lit = List(1, 2, 3, 4, 5, 6, 6,7,7, 8)
        lit.map(_ * 2).filter(x => x > 10).distinct.reverse.foreach(println(_))
    

    map的使用:map分为可变长和不可变长

     /**
          * 不可变长Map映射,长度和值一旦初始化后不能再次被改变
          */
    
        //通过对偶元组的方法创建映射
        val map0 = Map(("a", "A"), ("b", "B"), ("c", "C"))
        // 通过箭头方式创建Map映射
        val map1 = Map("a" -> "A", "b" -> "B", "c" -> "C")
        //两者进行混合创建Map映射
        val map3 = Map("a" -> "A", ("b", "B"), ("c", "C"))
    
        //++只是将两个映射合并形成新的map映射,原有的map映射并没有改变
        val newMap = map0 ++ map1
        println(newMap)
    
    
        /**
          * 可变长map映射,mutable包下
          */
    
        val map4 = mutable.Map("a" -> "A")
        map4.put("b", "B")
        map4 += ("c" -> "C", "d" -> "D")
        map4 += (("e", "E"), ("f", "F"))
        map4 ++= mutable.Map("j" -> "J", "h" -> "H", ("i", "I"))
        println(map4)
    
        /**
          * 移除map中的key
          */
        map4 -= "i"
        println(map4)
        map4 --= Set("i", "j", "f")
        println(map4)
        map4.remove("h")
        println(map4)
    
    
        /**
          * Map映射常用操作方法
          */
        //判断一个key是否存在,存在返回true,否则返回false
        println(map4.contains("a"))
        //获取key对应的值,注意如果通过map("Key")获取对应的值,应该进行key是否存在判断
        if (map4.contains("e")) {
          println(map4("e"))
        }
    
        //映射的get方法也是用来获取key对应的值,但是这个方法返回的是一个option对象,这个option对象有两个
        //子类,如果有key则返回Some(some对象中封装了key对应的值,可以通过Some的get方法获取值)对象,没有key则返回None对象
        println(map4.get("e").get)
        val value: Option[String] = map4.get("e")
        //isEmpty方法可以用来判断是Some对象还是None
        if (!value.isEmpty) {
          println(value.get)
        } else {
          println(value)
        }
    
    
        //如果key存在,则返回key对应的value,否则返回给定的默认值
        val v = map4.getOrElse("e", "EE")
        println(v)
    
    
    
        println("********************************")
        /**
          * LinkedHashMap 插入有序,会按照我们的插入顺序排序,因为底层是链表结构
          */
        val map5 = mutable.LinkedHashMap[String, String]()
        map5 += ("d" -> "D")
        map5 += (("a", "A"))
        map5("c") = "C"
        map5("b") = "B"
        println(map5)
    
        /**
          * SortedMap可以自动对Map的key进行排序
          */
        val map6 = mutable.SortedMap[String, String]()
        map6("c") = "C"
        map6("b") = "B"
        map6("a") = "A"
        println(map6)
    

    set集合

    特点和java一样无顺序不重复

    /**
          * 不可变长set集合
          */
        val set0 = Set(1, 2, 3, 4, 5)
        //++并没改变原有的set集合,只是将两个set进行合并形成新的set集合
        val newSet0 = set0 ++ Set(6, 7, 8, 9)
        println(newSet0)
    
    
        /**
          * 可变长set集合
          */
        val set1 = mutable.Set(1, 3)
        //+=或-=后面只能是半单个元素
        set1 += 1
        set1 += 2
        //++=或者 --=后面只能添加set集合
        set1 ++= mutable.Set(5, 6, 7)
        set1.add(12)
        println(set1)
    
        set1 -= 1
        set1 --= mutable.Set(1, 2, 3)
        println(set1)
    
    
        /**
          * set常用操作方法
          */
        println(set1.mkString(","))
        println(set1.size)
        println(set1.head)
        println(set1.last)
        println(set1.max)
        println(set1.min)
        println(set1.sum)
    
    
        /**
          * set的转换操作
          */
        set1.map(_ * 2).filter(x => x > 2).foreach(println(_))
    

    元组的使用

    scala的元组是用括号来表示的,获取元组的值用下划线来表示,角标从1开始。

    //定义一个元组
        val t1 = ("小明", "男", 25)
        //元组的下标是从1开始
        println(t1._1 + "=" + t1._2 + "=" + t1._3)
    
        //只有两个元素的元组被称之为对偶元组(key-value)
        val tuple2 = ("id", "123")
        println(tuple2._1 + "-" + tuple2._2)
    
        //可以将元组中的元素单独赋值给对应的变量
        val tuple3, (name, age, sex) = ("ximing", 12, "男")
        println(tuple3)
        println(name)
        println(age)
        println(sex)
    
        //数组的拉链操作转换成元组,如果数组中有多余的就会被舍弃掉
        val arr1 = Array("a", "b", "c", "d","e")
        val arr2 = Array("A", "B", "C", "D")
    
        val arr3: Array[(String, String)] = arr1.zip(arr2)
        println(arr3.toBuffer)
    

    结束

    本文没什么技术含量,只是闲暇是对自己知识的反复练习和记录。希望对读者有溢。

  • 相关阅读:
    浙大数据结构课后习题 练习二 7-2 Reversing Linked List (25 分)
    浙大数据结构课后习题 练习二 7-2 一元多项式的乘法与加法运算 (20 分)
    浙大数据结构课后习题 练习一 7-1 Maximum Subsequence Sum (25 分)
    浙大数据结构课后习题 练习一 7-1 最大子列和问题 (20 分)
    PAT Basic 1019 数字黑洞 (20 分)
    PAT Basic 1017 A除以B (20 分)
    PAT Basic 1013 数素数 (20 分)
    PAT Basic 1007 素数对猜想 (20 分)
    PAT Basic 1003 我要通过! (20 分)
    自动化运维——HelloWorld(一)
  • 原文地址:https://www.cnblogs.com/boanxin/p/11566530.html
Copyright © 2011-2022 走看看