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

    SCALA基础

    • 面向对象和面向函数的集成

      !!!!一切值都是对象,一切函数都是值!!!!

    • 函数时编程,一切都是函数

    • 数学式的语法思维

    ——————————————————————

    IDEA开发环境准备:

    1、安装JDK、SCALA环境

    2、IDEA安装scala插件

    3、创建maven工程,创建目录,设置为root source目录

    4、创建文件,后缀为scala

    5、scala可以直接与java交互

    ——————————————————————

    [TOC]

    ——————————————————————

    1、标识符

    • 字母数字标识符:使用字母或者下划线开头,$符号在SCALA中也被看做是字母,但应该尽量避免定义$开头的变量,因为SCALA存在保留变量以$开头
    • 符号:符号标识符包含一个或多个表示符,SCALA编译时会将符号转换为$开头的变量名,如:->会被转义为$column$minus$greater,可以看出会转义为$英文单词,因此在java中调用scala程序时要使用转义后的符号

    2、import导包

    • SCALA的import可以出现在任何地方,有效范围:从声明处开始到程序最后结束。
    • SCALA会默认导入java.lang._ ,scala._包,因此以scala开头的包使用时会省略包名的引用。

    3、变量与常量

    • vaR定义变量

      • 变量定义时必须赋值var A:Int =1
      • 变量定义的类型可以不指定,自动推断
      • 变量空值是_下划线,定义为空值时必须指定类型var A:Char=_

      (boolean空为false,数值空为0,字符空为?)

    • vaL定义常量

      • val和def都可以定义常量,但val只初始化一次,def每次都会初始化
      • 常量的引用地址是不可改变的
      • 因为只是一层引用地址,因此使用复合类型的常量时,复合类型内部的值是可变的。

    变量类型与java基本相同,但是SCALA中没有primitive基本类型,所有的值也都是对象,可以理解为只有包装类。

    emmmm ,还支持很奇怪的多行字符串 """i am multiparaph string"""

    4、变量类型结构

    • Any 顶级类型

      • AnyVal

        • Unit
        • Byte、Short、Int、Long、Float、Double、Char、Boolean
        • 空值:Nothing
      • AnyRef(java.lang.Object)

        • List
        • Option
        • MyClass
        • 空值:Null

    5、类型别名

    • type关键字,type 别名=类型 ,类似C语言中的typedef typedef sturct{}mystruct stu

    ——————————————————————————————

    流程语句语法

    1、while循环

    var i:Int=0;
    while(i<100){
        println(i)
        i=i+1
    }
    do{
        println(i)
        i=i+1
    }while(i<200)
    

    2、for循环

    val length:Int=100
    for(i:Int <- 1 to length){
        println(i*100)
    }
    for(i:Int <- 1 to(length,step)){
        ...
    }
    for(i:Int <- 1 to length by step)){
        ...
    }
    for(i:Int <- 1 until length){
        println(i*100)
    }
    for(i <- 1 until(length,step)){
        ...
    }
    //until 和 to 都是一种函数,也可以通过i.until(length)调用
    //until 和 to 创建的区间是相同的
    

    3、中断break和breakable

    • 关于Break和Continue,要导入包才可以使用
    impot import scala.util.control.Breaks.break
    impot import scala.util.control.Breaks.breakable
    
    • breakable(语句块),内部嵌套break即可跳出本次循环
    • 卸载breakable外面的break直接跳出循环
    • breakable即可打断的语句块,相当于在循环中又嵌套了一层可被打断的语句块,将代码写在其中即可实现continue

    4、多条件循环

    • 多重循环条件+分号;
    val num:Int = 10;
    for ( i: Int <- 1 to 10; if i%2==0;if i>5 ) 
    {     
        println( i * 100 );
    }yield i;
    //使用 yield 将fot将具有返回值,yield中记录的是符合条件的步变量i的值的集合。
    //可以看出for也是个函数
    

    5、数组

    泛型定义,中括号(java是尖括号)

    数组,取值用小括号(java是中括号)

    Array 不可变集合 ,元素内容可变,数组长度不可变

    ArrayBuffer 可变长数组

    • 万物皆函数,因此数组也是使用的小括号()
    • 定长数组
    //方式1
    var a:Array[String]=new Array[String](3)
    a(0)="hello"
    a(1)="scala"
    a(2)="world"
    //方式2
    var a2=Array("hello","scala")
    //方式三,区间数组
    var a3=Array.range(1,10,2)
    //1,3,5,7,9
    
    • 变长数组
    import scala.collection.mutable.ArrayBuffer
    var arrbuf:ArrayBuffer[String]=new ArrayBuffer[String]
    

    6、元组

    • Tuple可以包含不同类型的值,类型以实际存储的元素类型为准
    • 元组最多支持22个元素
    • 使用name._1访问name元组的第1个元素,元祖没有0号位
    • 元组的类型:元组的实际类型取决于它的分量的类型,比如的(2,"string")类型实际为 Tuple2[Int,String],而 (‘u’,’r’,”the”,1,4,”me”) 的类型为 Tuple6[Char,Char,String,Int,Int,String]
    Tuple[长度](类型列表)
    
    //元组声明方式一
    var tp1 = ("Mike", "123 ABC street", 58)
    println(tp1._1)
    println(tp1._2)
    println(tp1._3)
    //迭代元组
    tp1.productIterator.foreach{ i =>println("Value = " + i )}
    //元组声明方式二
    var tp2 = new Tuple3("Mike", "123 ABC street", 58)
    
    
    //元组声明方式三
    def mike = "Mike" -> 5   //键值对形式
    //输出scala.Tuple2
    mike.getClass
    //将元组元素依次赋给三个变量
    val(name, address, age) = tp1
    println(name)
    println(adrress)
    println(age)
    
    //元祖还可以这么玩
    var yz=(1,List(2,3),"xixi")
    val (id,order_id,name)=yz
    //有点类似于样例类
    

    1564123476174

    7、集合Collection

    1564023256574

    1564023499099

    1、序列Seq:List,Stack,Queue,Array

    2、集合Set

    3、映射Map

    8、mutable和immutable不可变集合

    复杂类型大都分为两类,MUTABLE和IMMUTABLE,可变的和不可变的,如ArrayBuffer就是一个可变集合,默认scala会选择不可变集合

    • 包名:scala.collection.mutable|immutable.

    • 可变集合:可以修改、添加或移除一个集合的元素

    名称可变/不可变示例
    Buffer mutable val buffer = scala.collection.mutable.ArrayBufferInt; buffer+=(2,3)
    Array mutable val arr=Array(1,2,3)
    List immutable val lst=List(1,2,3)
    Map mutable val stu= Map("name" -> "Jason", "age" -> "18")
    Set mutable/immutable val set=Set(1,2,3)
    Vector immutable val v=Vector(1, 3, 5, 7, 11, 13)
    Stack mutable/immutable val st=scala.collection.mutable.Stack(1,2,3) //堆栈,先进后出
    Queue mutable/immutable val q=scala.collection.mutable.Queue(1,2,3) //队列,先进先出
    BitSet mutable/immutable val bit=scala.collection.mutable.BitSet(3,2,0) //位集合
    ListMap immutable val map = scala.collection.immutable.ListMap(1->"one", 2->"two")
    HashSet mutable val set= scala.collection.mutable.HashSet(1,2,3)
    HashMap mutable val stu= scala.collection.mutable.HashMap("name" -> "Jason", "age" -> "18")

    9、集合常用操作

    1)List常用操作

    • 追加操作(新对象)

      • 用于不可变对象,会生成新对象:
      • +: 新加变量为主,在新变量后追加整个集合
      • :+ 集合为主,在集合的后面追加新变量
    • 扩充操作(本对象)

      • 用于可变对象,直接修改本list:
      • += 集合为主,在集合后面追加新变量
      • +=: 新加变量为主,在集合的前面追加新变量
      • ++=: 新加变量为主且该变量为List类型,在集合的前面追加新变量
    • 分组操作

      • grouped n(等价于list.grouped(n)),n个为一组
      • sliding(n,step),每次显示n个,,起始位置s是0。滚动显示,默认步长step为1

    2)Set常用操作

    • SortSet ,可以排序的set

    • Set,去重的

    • 增删操作

      • += 修改自身,追加一个内容
      • -= 修改自身,删除一个内容
      • -- 删除一系列内容
      • ++ 增加一系列内容
    • 逻辑运算

      • | 求并集intersect
      • & 求交集union
      • &~ 求差集diff

    3)Map常用操作

    4)Stream&Vector

    • Stream是惰性List,参数值只会在使用到的时候才会初始化
    • Vector是连续存储的List,访问效率比随机存储的list更高

    10、空值

    1. Nil 继承了List[Nothing类],指空List
    2. None 继承了Option[Nothing] 类,指的是Option的空值
    3. Null是指空引用类型,null是引用的空值
    4. Nothing 是Any的子类的,代表类型的的空(指没有类型,Null空类型也是一种类型),类型为空的变量必须是空的,没有实例

    函数

    一切函数都是值,一切值都是对象,一切对象都可以是函数

    def 函数名([参数列表]):[返回值类型]={
        print("我是个函数")
        return [表达式]  
        //return 是可选的,如果不定义,自动返回最后一个行的值
    }
    

    1)函数调用

    • 传值参数

      //假设调用时为square(1+2)
      def square(x:Int):Int={
          print(x) //3
          x*x //3*3
      }
      
    • 传名调用,x不计算,仅传递代码体

      • 与闭包搭配,外面修改x后,函数每次都会重新计算参数值因此会实时更新X
      def square(x: => Int):Int={  //注意空格
          print(x) //1+2,在print中计算
          x*x //(1+2)*(1+2)
      }
      

    !!!一切皆地址,函数也是地址,函数名只是引用的函数地址!!!

    2)函数参数/函数返回值

    语法结构:

    def 函数名(形参名:(形参函数参数类型表)=> 形参函数返回值类型):[返回值]={
    	//调用形参函数
        形参函数名(参数)
    }
    

    demo实例

    def myfun(fun:Int => Unit):Unit={
        fun(1)//注意,这里的fun是形参函数名
    }
    def fun(x:Int):Unit={
        print(x)
    }
    myfun(fun(1))
    //:Unit 可以省略 ,默认就是无返回值
    
    //参数为空
    def NullPara(){}
    或者
    def NullPara(null: =>String):String{}//省略了类型
    
    //常用高阶函数
    val l=List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    l.map(_*2).foreach(println)
    l.map(_*2).filter(_>8).foreach(println)l.fold(0)((sum,i)=>sum+i)
    l.take(4).foreach(println)//非高阶
    println(l.reduce(_+_))
    println(l.reduce(_-_))
    println(l.max)
    println(l.count(_>3))
    println(l.min)
    println(l.sum)
    
    val a=List(1,2,3,4)
    val b=List("A","B","C","D")
    println(a zip b)
    val c=List("A","B","C","D","E")
    println(a zip c)
    val d=List(1,2,3,4,5)
    println(d zip c)
    List("zhangsan","lisi","wangwu").zip(List(100,90,75,83))
    
    val f=List(List(1,2),List(3,4),List(5,6))
    println(f.flatten)
    println(f.flatMap(_.map(_*2)))
    

    3)匿名函数

    • 关键字符:=>
    • 左边为(函数参数),右边为{ 函数体 }
    (x:Int)=>{print(x)}
    //因为匿名,没有引用变量,没法直接使用,要么赋值给变量,要么作为实参
    
    myfun((x:Int)=>{print(x);print(x+x)})
    //一般使用在函数参数处
    //多条语句使用分号隔开
    
    • scala内置的大部分接口函数都支持匿名函数,可以自定义匿名函数作为foreach和map函数的参数

    4)函数变量& def关键字

    a)函数变量

    //函数有参时
    var funVar=myfun _  //相当于引用了函数地址
    var funvalue=myfun  //报错
    def funbody=myfun _	//相当于重名名函数
    //使用下划线缺省函数参数
    //可以说val其实是拿到了函数de返回值
    
    //函数无参时
    var funvar=myfun  //无参myfun等价于myfun(),执行函数并返回值给funvar
    
    funVar("xixi")
    
    • var或者val定义的函数变量:定义时执行一次函数体,之后每次调用只能得到函数体的返回值return值
    • def定义的函数变量:定义时不执行函数体,之后每次调用都会完整的运行一遍函数体

    b)def关键字

    • def不仅仅用于定义函数和函数变量

    5)嵌套函数

    • 函数中可以再次定义函数,这个子函数只有在本函数内可见。

      def factorial(i: Int): Int = {
            def fact(i: Int, accumulator: Int): Int = {
               if (i <= 1)
                  accumulator
               else
                  fact(i - 1, i * accumulator)
            }
            fact(i, 1)	//不能在factorial()之外调用
         }
      

    6)cury柯里化

    demo实例

    def sum(x:Int)(y:Int)={
        print(x+y)
    }
    

    柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

    • 子函数依次产生,每个子函数根据当前参数返回新的子函数。
    • 参数1--->子函数1(参数2)--->子函数2(参数3) >>>>>最终返回函数的最终返回值
    • 更加灵活的调用同一个函数

    灵活运用demo

    def sum(x:Int)(y:Int)={
        print(x+y)
    }
    def f1(x:Int)=sum(1)(x)
    def f2(y:Int)=sum(x)(2)
    def f3(z:Int)=sum(3)_
    def f4(g:Int)=sum_(4)
    def f5(()()=>)
    

    7)隐式函数/隐式参数

    demo参数

    implict var today="2018-10-25"
    def mkLog(arg:String,implict date:String){
     	print(date+" "+arg)
    }
    mkLog("Success") //运行成功,作用域内找到合适类型的参数,使用隐式参数
    mkLog("Success","2018-1-1") //运行成功
    

    demo 函数

    "100"/10   //ERROR 类型错误
    def String2Int(str:String)={
        str.toInt
    }
    "100"/10  //类型错误-->发现合适的类型转换函数-->调用-->隐式转换
    res1:10
    
    • 隐式转换和调用只会发生在发生类型错误的时候
    • 两者都需要有implict声明
    • 只能发生在当前作用域内进行值和函数的查找

    8)命名参数&参数缺省值

    • 命名参数:即在调用函数的时候声明值的形参名

      def function(str1:String,str2:String){
          print(str1+str2)
      }
      function(str2="xixi",str1="haha");
      //res1:hahaxixi
      
    • 参数缺省值:即在定义函数的时候给出参数的default值

      def sum(a:Int=1,b:Int=2){
      print(a+b)
      }
      sum()
      //res1:3
      //与命名参数一起使用更佳
      sum(b=10)
      //res2:11
      sum(10)
      //res3:12
      

    常用高阶函数

    • 高阶函数,以函数作为参数

    ————————————————————————————————

    1、map

    • 集合的函数映射,生成新的集合

    2、foreach

    • 相当于for循环内部函数体

    3、filter

    • 自定义函数过滤器
    lst.filter((x:Int)=>x>50)
    lst.filter(_>50)
    //参数函数返回值为true的元素才会被保留
    

    4、reduce

    lst.reduce(_+_)
    lst.reduce((x:Int,y:Int)=>{x+y})
    

    5、fold

    lst.fold(5)(_+_)
    //与reduce相似,但有一个预先值作为第一个值
    
    //foldRight 从右侧开始
    

    6、zip

    //类似于拉链,逐个嵌套
    var lst2=lst.map(_*2)
    lst1.zip(lst2)
    //生成了键值对列表
    //长度以最短的list为准
    

    7、flatten

    //将复杂类型的内部嵌套展开
    //只保留最外层的复杂类型结构
    var map1=lst.map(x=>List(x))
    map1.flatten
    map1.flatten(_.map(_*2))
    

    8、flatMap

    //先对子复杂结构进行map
    //然后flatten各子元素map的结果
    map1.flatMap(_.map(_*2))
    
  • 相关阅读:
    马云:员工的离职原因--转载
    zookeeper源码分析之五服务端(集群leader)处理请求流程
    技术高手如何炼成?--转自知乎
    一次上线事故经验
    zookeeper源码分析之四服务端(单机)处理请求流程
    AngularJS2.0 quick start——其和typescript结合需要额外依赖
    typescript 入门例子 Hello world——ts就是一个宿主机语言
    Kubernetes——自动扩展容器!假设你突然需要增加你的应用;你只需要告诉deployment一个新的 pod 副本总数即可
    Kubernetes——基于容器技术的分布式架构领先方案,它的目标是管理跨多个主机的容器,提供基本的部署,维护以及运用伸缩
    华为FusionSphere概述——计算资源、存储资源、网络资源的虚拟化,同时对这些虚拟资源进行集中调度和管理
  • 原文地址:https://www.cnblogs.com/whoyoung/p/11424428.html
Copyright © 2011-2022 走看看