scala教程

  • scala常用版本与开发工具
    常用版本为2.11.8
    开发工具采用IDEA

  • 基于idea的scala项目开发
    在这里插入图片描述
    在这里插入图片描述
    在pom.xml中
    将依赖的版本号进行封装

     <properties>
        <scala.version>2.11.8</scala.version>
      </properties>
      <dependency>
          <groupId>org.scala-lang</groupId>
          <artifactId>scala-library</artifactId>
          <version>**${scala.version}**</version>
       </dependency>
    
  • 基础语法
    var 变量->可变的
    val 值->不可变的(工作中首选)

    定义float类型变量需要给值后面加f
    定义Long类型变量需要给值后面加L

     10.isInstanceOf[Int] 判断是否为Int类型返回布尔值
     10.asInstanceOf[Long] 将Int类型转换为Long类型
    

    当定def的时候方面没有参数,在调用的时候不用加()

    1 to 10 / 1.to(10) [1,10]
    1 until 10 / 1.until(10) [1,10)
    Range(1,10,2) 这里面的2代表步长
    Range(10,1,-1)

      for (i<- 1 to 10 if(i%2 == 0)){
            println(i)
          }
    
  • 默认参数*****

      //默认参数: = "考拉"
      def sayName(name:String = "考拉")={
        print(name)
      }
    

    可以直接调取sayName()这里不允许去掉括号,也可以传参进去

  • 命名参数*

    //命名参数 
      def speed(distance:Float,time:Float)={
        distance/time
      }
      ===============
      调用:print(speed(time=10,distance = 100))
    

    调用的时候,直接传递参数名

  • 变长参数****

    //变长参数
      def sum(a:Int*) = {
        var result = 0
        for (ele <- a){
          result+=ele
        }
        result
      }
      ======================
      调用:print(sum(0,2,3,4,5,6,6))
    

    变长参数需要在方法的参数中类型后面加星号
    但是如果调用sum(1 to 10)就会报错,因为1 to 10返回的是Range,所以这里需要 ==sum(1 to 10 : _*)==这种固定写法

  • 面向对象编程*****

    //class用于定义一个类
    class People {
      //类里面定义属性
      var name = ""
      var name1:String = _
    
      val age = 10
    
      def code() = {
        name + "coding..."
      }
    }
    

    类中定义属性有两种方式,如上面的name,name1
    在这里插入图片描述
    _写法的默认值

    private[this] var gender = "male"
    

    再类中定义这种属性,表示属性是私有的,在类外部是无法进行访问的(了解),这种方式一般出现在源码中,自己编程很少用到

  • 构造器*****

    package com.kaola.bigdata.scala02
    
    /**
      * 构造器
      */
    object ConstructApp {
    
      def main(args: Array[String]): Unit = {
        //new的时候,其实是调用的构造方法
        //val person = new Person("考拉", 30)
    
        //先走继承的主构造方法,然后在走student的构造方法
        val stu = new Student("kaola",30,"IT")
        println(stu.name+";"+stu.age+";"+stu.major)
        println(stu)
      }
    }
    //  print(person.name)
    
    
    
    //主构造器
    class Person(val name:String,val age:Int) {
      println("~~~~~~Peron enter~~~~~~~")
      val school = "ustc"
      println("~~~~~~Peron leave~~~~~~~")
      var gender = "male"
    
      /**
        * 附属构造器def this
        *
        * 第一行必须要调用已有的主构造器,或者附属构造器
        *
        * @param name
        * @param age
        * @param gender
        */
      def this(name: String, age: Int, gender: String) {
        this(name, age) //必须要有的
        this.gender = gender
      }
    }
    
    //如果继承的父类中没有相应属性,需要用val修饰,如下,切记
    class Student(name:String,age:Int,val major:String) extends Person(name,age){
      println("~~~~~~Student enter~~~~~~~")
    
      //父类属性或方法需要使用override
      override val school: String = "拉翔"
    
      override def toString() = "Student toString"
    
      println("~~~~~~Student leave~~~~~~~")
    }
    
  • 抽象类

    package com.kaola.bigdata.scala02
    
    /**
      * 抽象类
      * 1)一个或者多个方法只有定义没有实现
      * 2) 不能直接使用,必须有实现类
      */
    object AbstractApp {
      def main(args: Array[String]): Unit = {
        val s = new Student2()
        s.hit
      }
    }
    
    abstract class Person2 {
      def hit
    
      val name:String
    }
    
    class Student2 extends Person2{
      override def hit: Unit = {
        println("王六六在那被打!")
      }
    
      override val name: String = "kaola"
    }
    
  • 伴生与apply方法的使用*****

    package com.kaola.bigdata.scala02
    
    
    /**
      * 互为伴生,下面有ApplyTest的class与object
      */
    class ApplyTest {
      def test() = {
        println("class ApplyTest~~~~~test")
      }
    
      def apply() = {
        println("class ApplyTest apply")
      }
    }
    
    object ApplyTest {
      println("object ApplyTest~~~~~enter")
      var count = 0
    
      def inc() = {
        count = count + 1
        count
      }
    
      def static() = {
        println("object ApplyTest static")
      }
    
      def apply() = {
        println("object ApplyTest apply")
        new ApplyTest //偷偷的new了一个ApplyTest对象
      }
    
      println("object ApplyTest~~~~~leave")
    }
    
    object ApplyApp {
      def main(args: Array[String]): Unit = {
        //object定义的直接类名.方法,不需要使用new
        println(ApplyTest.inc())
    
        //class定义的需要new
        //val a = new ApplyTest()
        //println(a)
    
        val b = ApplyTest() //这个很重要,相当于调用了object的ApplyTest+apply()方法
        b.test() //class
    
        val c = new ApplyTest
        c() //相当于调用了class的apply()==()
      }
    }
    
    结果:
    object ApplyTest~~~~~enter
    object ApplyTest~~~~~leave
    1
    object ApplyTest apply
    class ApplyTest~~~~~test
    class ApplyTest apply
    
  • case class*****

    package com.kaola.bigdata.scala02
    
    object CaseClassApp {
      def main(args: Array[String]): Unit = {
        //不需要new直接调用
        println(Dog("kaola").name)
      }
    }
    
    case class Dog(name:String)
    
    
  • 集合*****

    • 数组
      两种定义方式,其中第二种定义方式就是采用了object->apply的方法中new了Array

      	 //定长数组
          val a = new Array[String](5)
          val b = Array("考拉","王六六")
          
      	//第二种定义的源码
      	def apply[T: ClassTag](xs: T*): Array[T] = {
      	 val array = new Array[T](xs.length)  //调用了new方法
      	 var i = 0
      	for (x <- xs.iterator) { array(i) = x; i += 1 }
      	 array
      	}
      
      package com.kaola.bigdata.scala02
      
      import scala.collection.mutable.ArrayBuffer
      
      object ArrayApp {
        def main(args: Array[String]): Unit = {
      
          //定长数组
          val a = new Array[String](5)
          //数组长度
          a.length
          //赋值
          a(1) = "ruozedata"
      
          val b = Array("考拉", "王六六")
          //可能会用到的方法,拼接
          val str1 = b.mkString(",")
          //传入三个参数就会左右包围
          val str2 = b.mkString("[",",","]")
          println(str1)
          println(str2)
      
          //变长数组
          val c = ArrayBuffer[Int]()
          c+=1 //添加元素
          c+=2
          c+=(2,3,4,5) //一次添加多个元素
          c++=Array(6,7,8) //添加个array
          c.insert(0,0) //指定位置添加元素
          c.remove(1) //删除指定位置元素
          c.remove(1,3) //删除从指定index之后的几个元素
          c.trimEnd(2) //删除后几个元素
          val cArr = c.toArray //将ArrayBuffer转成array
          //遍历1
          for(i<-0 until(cArr.length)){
            println(cArr(i))
          }
          //遍历2(常用)
          for(ele<-cArr){
            println(ele)
          }
      
        }
      }
      
      
    • list
      Nil是定义了一个空的List

      scala> Nil
      res0: scala.collection.immutable.Nil.type = List()
      ##head是取第一个元素
      scala> l.head
      res1: Int = 1
      ##tail是去除了第一个元素后面的list
      scala> l.tail
      res2: List[Int] = List(2, 3, 4, 5)
      ##用::可以拼接list
      scala> val l2 = 1::Nil
      l2: List[Int] = List(1)
      scala> val l3 = 2::l2
      l3: List[Int] = List(2, 1)
      scala> val l4 = 1::2::3::Nil
      l4: List[Int] = List(1, 2, 3)
      
      package com.kaola.bigdata.scala02
      
      import scala.collection.mutable.ListBuffer
      
      object ListApp {
        def main(args: Array[String]): Unit = {
          //定长的list
          val list = List(1,2,3,4,5)
          //不定长list
          val lb = ListBuffer[Int]()
          lb+=2 //往list中添加元素
          lb+=(3,4,5) //添加多个元素
          lb++=List(6,7,8) //添加list
          lb-=2 //删除list中的值
          lb-=(1,4) //没有的话也不会报错
          lb.toArray
          lb.toList
          lb.isEmpty
      
          println(sum(1,2,3,4,5))
        }
      
        //递归的方式求和,list或者array如果想作为变长的参数传入需要加上:_*
        def sum(nums:Int*):Int = {
          if(nums.length == 0) {
            0
          }else {
            nums.head+sum(nums.tail:_*)
          }
        }
      }
      
      
    • Map

      package com.kaola.bigdata.scala02
      
      object MapApp {
        def main(args: Array[String]): Unit = {
          //不可变的map,无法修改,用的少
          val map = Map("kaola" -> "dingding", "wangliuliu" -> "sha")
          map("kaola")
          //常用的是HashMap,可变的map
          val b = scala.collection.mutable.HashMap("kaola" -> "dingding", "wangliuliu" -> "sha")
          b("kaola") = "yaya"
          //在spark中很常用,如果没有key就使用默认值而不报错
          b.getOrElse("gender", "unknown")
          b += ("" -> "") //添加key value
          b -= ("kaola") //删除key value
      
          //遍历1
          for ((key, value) <- b) {
            println(key+":"+value)
          }
          //遍历2
          for((key,_)<-b){
            println(key+":"+b.getOrElse(key,0))
          }
          //遍历3
          for(ele<-b.keySet){
            println(ele+":"+b.getOrElse(ele,0))
          }
          //遍历values
          for(ele<-b.values){
            println(ele)
          }
        }
      }
      
      
    • Option

      package com.kaola.bigdata.scala02
      
      /**
        * some与none都是继承的Option
        */
      object OptionApp {
        def main(args: Array[String]): Unit = {
          val map = Map(1->2)
          println(map(1)) //打印出2
      
          println(map.get(1)) //打印出Some(2)
      
          println(map.get(2)) //虽然没有,但是打印出None
      
          println(map.get(1).getOrElse(0)) //常用方式
        }
      }
      
  • 高阶函数*****

    package com.kaola.bigdata.scala03
    
    /**
      * 高阶函数
      */
    object AdFunctionApp {
      def main(args: Array[String]): Unit = {
        val l = List(1, 2, 3, 4, 5)
    
        //对集合中的每个元素都做一个操作:*2
        println(l.map((x: Int) => x * 2)) //=>左边是输入,右边是输出
        //如果一个参数,较好的写法
        println(l.map(x => x * 2))
        //还有一种非常非常重要的写法,一定要掌握的
        println(l.map(_ * 2))
    
        //foreach
        l.map(_ * 2).foreach(x => println(x))
    
        //filter
        l.map(_ * 2).filter(_ > 8).foreach(x => println(x))
    
        //reduce,两两相邻的值加起来
        println(l.reduce(_ + _))
        l.reduceLeft(_ + _) //与reduce相同,从左往右
        l.reduceRight((x, y) => {
          println(x, y)
          x - y
        })
    
        //fold,表示有个初始值为10与l进行结合,有面试被问到过
        println(l.fold(10)(_+_))
        //常用函数
        println(l.min+":"+l.max+":"+l.sum)
        //count中必须传入判断函数
        println(l.count(_>3))
      }
    
      def sum(a: Int, b: Int) = a + b
    
      //curry,调用的时候采用add(1)(2)
      def add(a: Int)(b: Int) = a + b
    
    }
    
    
    这是上面代码中的reduceRight方法的执行过程
    (4,5)
    (3,-1)
    (2,4)
    (1,-2)
    
  • 文件操作

    package com.kaola.bigdata.scala03
    
    import scala.io.Source
    
    /**
      * 文件操作
      */
    object FileApp {
      def main(args: Array[String]): Unit = {
        //读文件
        val file = Source.fromFile("/Users/apple/Desktop/people.txt")
        for(line<-file.getLines()){
          println(line)
        }
    
        Source.fromURL("") //请求接口
    
    
      }
    }
    
    
  • String的简单操作

    package com.kaola.bigdata.scala03
    
    object StringApp {
      def main(args: Array[String]): Unit = {
        val name = "考拉"
        println("hello:"+name)
        println(s"hello:$name") //字符串插值
    
        val b =
          """
            |定定定
            |牙牙牙
            |乐乐乐
          """.stripMargin
        println(b)
      }
    }
    
    
  • 隐式转换(少写这个,容易让别人看不懂,但是面试会被问到)*****

    package com.kaola.bigdata.scala03
    
    import java.io.File
    
    import scala.io.Source
    
    /**
      * 隐式转换,增强类的功能
      */
    object ImplicitApp {
      def main(args: Array[String]): Unit = {
        //隐式将man转化superman,可以调用superman中的方法
        implicit def man2superman(man:Man):SuperMan = new SuperMan(man.name)
    
        val man = new Man("kaola")
        man.fly()
    
        implicit def file2RichFile(file:File):RichFile = new RichFile(file)
    
        val file = new File("/Users/apple/Desktop/people.txt")
        //本来file是没有read方法的,加入隐式转换就可以做到
        println(file.read())
      }
    }
    
    class Man(val name:String)
    
    class SuperMan(val name:String) {
      def fly() = {
        println(s"$name 会飞了")
      }
    }
    
    class RichFile(val file:File){
      def read() = Source.fromFile(file.getPath).mkString
    }
    
    

    但是这里最好把implicit的东西抽出来,所以这里定义了一个ImolictAspect

    package com.kaola.bigdata.scala03
    
    import java.io.File
    
    object ImolictAspect {
      implicit def man2superman(man:Man):SuperMan = new SuperMan(man.name)
      implicit def file2RichFile(file:File):RichFile = new RichFile(file)
    }
    
    

    但是切记主类中一定要import包import ImolictAspect._

  • 模式匹配*

    package com.kaola.bigdata.scala03
    
    import scala.util.Random
    
    /**
      * 模式匹配
      */
    object MatchApp {
      def main(args: Array[String]): Unit = {
        val teachers = Array("Aoi Sola", "YuiHatano", "Akiho Yoshizawa")
    
        val teacher = teachers(Random.nextInt(teachers.length))
        //    for(i<-1.to(10)){
        //      val teacher = teachers(Random.nextInt(teachers.length))
        //      println(teacher)
        //    }
        teacher match {
          case "Akiho Yoshizawa" => println("1")
          case "YuiHatano" => println("2")
          case _ => println("3")
        }
        //异常中使用模式匹配
        try {
          val i = 1 / 0
          println(i)
        } catch {
          case e: Exception => println("捕获到一个异常")
          case e: ArithmeticException => println("除数不能为0")
        } finally {
          println("这行代码是一定要执行的")
        }
      }
    
      //数组匹配
      def greeting(array: Array[String]) = {
        array match {
          case Array("zhangsan") => println("hi:zhangsan")
          case Array(x, y) => println(s"hi:$x")
          case _ => println("welcome...")
        }
      }
    }
    
    
  • 偏函数*

    package com.kaola.bigdata.scala03
    
    /**
      * 偏函数
      * 被包在花括号内没有match的一组case语句是一个偏函数
      */
    object PianFunctionApp {
      def main(args: Array[String]): Unit = {
        sayChineseName("jklsdfjisl")
        println(pianSayChineseName("jklsdfjisl"))
      }
      //正常用match
      def sayChineseName(name:String) = name match {
        case "jklsdfjisl"=>println("考老师")
        case _=>println("听不懂")
      }
      //偏函数
      def pianSayChineseName:PartialFunction[String,String] = {
        case "jklsdfjisl"=>"考老师"
        case _=>"听不懂"
      }
    
    }
    
    
Martin Odersky 用他定义的匹萨语言给了 Java世界一个很大的冲击。尽管匹萨本身没有流行 但它展现了当把面向对象和函数型语言两种风格,技术地且很有品地混搭在一起时,就形成了 自然和强有力的组合。匹萨的设计成为了 Java泛型的基础,马丁的 GJ(Generic Java)编译 Java 1.3开始成为了 Sun 微系统的标准编译器(尽管关闭了泛型)。我有幸能够维护这个编译 年,因此我能通过第一手经验从语言设计到语言的实现方面(向大家)报告马丁的技术。 那时候我们还在 Sun 公司,尝试用一些零打碎敲的特定问题解决方案来扩展语言,如 for-eac 环,枚举,自动装包,去简化程序开发的时候,马丁则继续着他在更强大的正交语言原语方面 作以帮助程序员用库来提供解决方案。 后来,静态类型语言受到了冲击。Java 的经验说明了静态语言编程会导致大量的固定写法的代 通常认为我们应该避免静态类型从而消除这种代码,于是人们对动态语言如 Python,Rub Groovy的兴趣开始增加。这种认知被马丁最近的作品,Scala,的出现打破。 Scala 是一种很有品味的类型语言:它是静态类型的,但仅在需要的地方显式定义类型。Scala 向对象和函数式语言两方面获得了强大的特性,然后用一些新奇的点子把它们漂亮地整合成一 它的语法是如此的轻量级,而原语又如此富有表达力,以至于根本可以认为 API的使用不须负 法开销。我们可以在标准库中,如拆分器、组合器和执行器,中发现例子。从这点上看,Scal 一种支持内嵌的域特化:embedded domain-specific 的语言。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值