scala入门基础

  • scala下载和安装

命令行使用
  1. JAVA8环境
  2. scala下载
  3. unzip scala
  4. 配置环境变量
  5. 启动 ./scala
基本数据类型

和java类型一致

  • var 和 val
    var 变量
    val 常量
  • asInstanceOf[数据类型]
    类型转换函数
  • isInstanceOf[数据类型]
    判断是否是某一数据类型
  • lazy
    修饰符,延迟加载
Scala函数
  • 方法的定义和使用
    def 函数名(参数名:参数类型):函数返回值类型 = {函数体,最后一行为返回值,不需要return,只有一行可不加大括号}
    无参函数调用可直接使用函数名
  • 默认参数
    (参数名:参数类型 = 默认参数)
  • 命名参数
    调用函数的时候根据名字调用参数,可以不按顺序
  • 可变参数
    (参数名:参数类型*)
  • 循环表达式
    to:(1 to 10)、(1.to(10))两种用法,包含始末;
    until:用法同to,不包含末尾;
    Range:Range(start, end, step)
    for(x <- 1 to 10 if x % 2 == 0) {
        println(x)
    } 
    val courses = Array("hadoop", "spark", "mapreduce", "hive")

    for(course <- courses){
      println(course)
    }

    courses.foreach(x => {
      println(x + 1)
    })
    var (num, sum) = (100,0)
    while(num>0){
      sum = sum + num
      num = num -1
    }
    println(sum)
  • yield
  /**
    * 针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
    * 当循环结束后, 会返回所有 yield 的值组成的集合.
    * 返回集合的类型与被遍历的集合类型是一致的.
    */

  val a = Array(1,2,3,4,5)
  val ret = for(e <- a) yield {
    println(e)
    e * 2
  }
  ret.foreach(println)
scala 对象
scala 集合
  • 定长数组
  val a = new Array[String](5)
  a(1) = "hello"
  println(a(1))

  val b = Array("hello", "world", "are", "you", "ok")
  for(x <- b){
    println(x)
  }

  val c = Array(1, 2, 3, 4, 5)
  println(c.sum)
  println(c.max)
  println(c.mkString("(",",",")"))
  • 变长数组
  val c = scala.collection.mutable.ArrayBuffer[Int]()

  c += 1
  c += (2, 3, 4)
  c ++= Array(5, 6, 7)

  c.insert(0, -2, -1, 0)
  c.remove(0,3)
  c.trimEnd(2) //从末尾移除
  
  val d = c.toArray
  • List
  val a = Nil  //Nil是空的List

  //List 由head和tail组成
  val b = List(1,2,3,4,5) //定长List
  val c = 1 :: Nil
  val d = 1::3::5::Nil

  println(d.head+d.tail.mkString)

  val e = scala.collection.mutable.ListBuffer[Int]() //变长List

  e += (1,2,3) //和可变数组用法一致
  e -= (2,3)

  println(e.head)
  println(e.tail) //ListBuffer类型

  def sum(nums: Int*):Int = {
    if(nums.length == 0){
      0
    } else {
      nums.head + sum(nums.tail:_*)  //递归操作,:_*将某个参数当做参数序列处理
    }
  }
  • Set
  //和上述类型用法一致,有定长和变长
  val a = Set(1,2,3,4,5)

  val b = scala.collection.mutable.Set[Int]()

  b += 4
  println(b.toList.length)
  • Map
  /**
    * Map初始化的两种方式
    */
  val m1 = Map(("name", "Tom"), ("age", 18))
  val m2 = Map("name"->"Tom", "age"->18)
  /**
    * map get返回Option类型对象:Some或NONE
    * 有下列三种获取方式,可以当做集合处理
    */
  val o = m2.get("name")
  println(o.getOrElse("no value"))
  o match {
    case Some(o) => println(o)
    case None => println("no value")
  }
  o.foreach(println)

  println(m2("name")) //直接获取map key对应的value,会抛出异常
  println(m2.getOrElse("name","no value"));

  /**
    * 不可变Map,返回新的Map
    */
  m2 + ("address"->"广州")
  val m3 = m1 + ("hobby" -> "篮球", "job" -> "程序员")

  m2 ++ m1

  //m2 - ("hobby","job")
  m2 -- m1.keySet //接收key的集合

  m3.keysIterator.foreach(x => println("key: "+ x + "; value: "+ m3(x)))

  val m = scala.collection.mutable.Map[String,Int]("A"->100, "B"->90)

  /**
    * 新增和移除和其它可变集合一致
    */
  m += ("C" -> 70)
  m += ("D" -> 60, "F" -> 50)
  m ++= Map("E" -> 80)
  m --= m1.keySet
  m.keysIterator.foreach(x => println("key: "+ x + "; value: "+ m(x)))

  /**
    * 作缓存
    */
  val cache = collection.mutable.Map[String, String]()
  def f = (s: String) => {
    print("waste my time"); Thread.sleep(1000)
    s.reverse
  }

  def cacheF = (s:String) => cache.getOrElseUpdate(s, f(s))

  println(cacheF("abc"))
  println(cacheF("abc")) //第二次调用因为是相同的name,所以直接从map中取值
  • Tuple
  val tuple = ("scala", 1)
  println(tuple._1)
  println(tuple._2)

  //支持解构
  val (course, score) = tuple
  println(course)
  println(score)

  //支持模式匹配
  val planetDistanceFromSun = List(("Mercury", 57.9), ("Venus", 108.2), ("Earth", 149.6 ), ("Mars", 227.9), ("Jupiter", 778.3))
  planetDistanceFromSun.foreach{ tuple => {
    tuple match {
      case ("Mercury", distance) => println(s"Mercury is $distance millions km far from Sun")
      case p if(p._1 == "Venus") => println(s"Venus is ${p._2} millions km far from Sun")
      case p if(p._1 == "Earth") => println(s"Blue planet is ${p._2} millions km far from Sun")
      case _ => println("Too far....")
    }
  }
  }
  //循环表达式
  val numPairs = List((2, 5), (3, -7), (20, 56))
  for ((a, b) <- numPairs) {
    println(a * b)
  }
类和对象
  • 类和属性的定义
package com.test

class ScalaClass {
  //val 修饰的属性,系统会自动生成get方法
  val id:String = "123456"
  //var 修饰的属性,系统会自动生成get和set方法
  var name:String = ""
  //private var修饰的属性,系统会自动生成private修饰的get和set方法
  private var gender_ :Int = 0

  //私有成员的get和set方法,set方法为get函数名加上‘_=’,后面加上参数
  def gender = gender_
  def gender_=(newValue: Int) = {
    if(newValue < 18){
      println("你是未成年")
      gender_ = newValue
    } else{
      println("成年人不许进入")
    }
  }

  //只有当前对象可以访问该属性
  private[this] var age:Int = 32

  //不是当前对象,第四种会提示报错
  def getGender(cla: ScalaClass) :Int = {
    cla.gender_
  }

  def getAge():Int = {
    age
  }

}

object test {
  def main(args: Array[String]): Unit = {
    val cla = new ScalaClass()
    cla.name = "tom"

    /**
      *需实现上面的get和set方法才能调用下面的set操作
      */
    cla.gender = 17
    println("name: "+cla.name+" id: "+cla.id+" gender: "+cla.getGender(cla)+" age: "+cla.getAge())
  }
}
  • 构造函数
package com.test

/**
  * 类自带无参的构造函数
  * 主构造函数执行类中所有的语句
  * 构造函数分为主构造函数和辅助构造函数
  */
class ConstructClass {
  var a:Int = 0

  println("hello world")

  //定义辅助构造函数
  def this(a1:Int){
    //辅助构造函数必须调用主构造函数或其他辅助构造函数
    this()
    this.a = a1
  }
}

/**
  * 定义带参的主构造函数,带var的参数是类的属性,不带则是普通的参数
  * 带private则是私有构造函数
  */
class ConstructClass1 private (var b1:Int) {
  var a:Int = 0

  println("hello world")

  //定义辅助构造函数
  def this(a1:Int, b1:Int){
    //辅助构造函数必须调用主构造函数或其他辅助构造函数
    this(b1)
    this.a = a1
  }
}

object testConstruct{
  def main(args: Array[String]): Unit = {
    val cla = new ConstructClass(3)
    val cla1 = new ConstructClass1(2,3)
    println(cla.a)
  }
}
  • 单例对象和伴生对象
/**
  * 单例对象,只初始化一次
  * 可作工具类使用
  */
object ObjectClass {
  def showInfo (msg: String)= {
    println(s"message info: $msg")
  }
}

class InfoClass {

  def useObjectClass(msg:String) = {
    ObjectClass.showInfo(msg)
  }
}

object testObject {
  def main(args: Array[String]): Unit = {
    ObjectClass.showInfo("hello")
    def obj = new InfoClass()
    obj.useObjectClass("bye")
  }
}
import scala.math._

/**
  * 伴生类和伴生对象
  * 可以互相访问彼此的私有属性和方法
  */
class ObjectClass(radius: Double){
  import ObjectClass._
  def area: Double = calculateArea(radius)
}
object ObjectClass{
  private def calculateArea(radius: Double) = Pi * pow(radius, 2.0)
}

object testObject{
  def main(args: Array[String]): Unit = {
    val obj = new ObjectClass(5.0)
    println(obj.area)
  }
}
  • apply和unapply
/**
  * apply和unapply方法
  */

class User(val name:String, val password:String){

}
object  User{
  //创建对象不需要new,直接会调用apply方法
  def apply(name:String, password:String) = new User(name, password)
  //模式匹配会调用unapply方法,返回所需字段
  def unapply(arg: User): Option[(String, String)] = {
    if(arg == null){
      None
    } else{
      Some(arg.name,arg.password)
    }
  }
}
object ApplyTest {
  def main(args: Array[String]): Unit = {
    val obj = User("tom","123456")
    println(obj.name+":"+obj.password)

    obj match {
      case User(name, password) => println(name+":"+password)
      case _ => println("none")
    }
  }
}
  • 继承
object extendTest {
  def main(args: Array[String]): Unit = {
    val obj = new Location(1,11,2)
    val obj1 = new Point(1,2)
    println(obj.isInstanceOf[Point])
    println(obj.isInstanceOf[Location])
  }
}

class Point(val xc :Int, val yc :Int){
  var x:Int = xc
  var y:Int = yc

  def move(dx:Int, dy:Int ): Unit ={
    x = x + dx
    y = y + dy
    println("x 坐标:"+ x)
    println("y 坐标:"+ y)
  }
}

/**
  * 继承了父类的所有属性和方法
  * 重写父类的非抽象方法,要用override
  * 重写父类的抽象方法,override可选择
  */
class Location(override val xc:Int,override val yc:Int, val zc:Int) extends Point(xc, yc){
  var z:Int = zc

  override def move(dx: Int, dy: Int): Unit = super.move(dx, dy)

  def move(dx:Int, dy:Int, dz:Int): Unit ={
    x = x + dx
    y = y + dy
    z = z + dz
    println("x 坐标:"+ x)
    println("y 坐标:"+ y)
    println("z坐标:"+ z)
  }
}
  • 特质
/**
  * 带有抽象方法的特质
  */
trait Iterator[A]{
  val num:Int
  def hasNext:Boolean
  def next:A
}

/**
  *带有实现的特质
  */
trait InfoLogger{
  def showLog(msg:String): Unit ={
    println(msg)
  }
}
//类可以继承多个特质
class IntIterator(val to: Int) extends Iterator[Int] with InfoLogger {
  private var current:Int = 0
  override val num: Int = to
  override def hasNext: Boolean = to > current

  override def next: Int = {
    if(hasNext){
      showLog("still hasNext")
      val t = current
      current += 1
      t
    } else{
      0
    }
  }
}

object TraitTest {
  def main(args: Array[String]): Unit = {
    val obj = new IntIterator(10)
    println(obj.next)
    println(obj.next)
    println(obj.next)
    println(obj.next)
    println(obj.next)
    println(obj.next)
  }
}
trait Info{
  def log(msg: String)
}

trait ConsoleInfo extends Info{
  override def log(msg: String): Unit = {
    println(msg)
  }
}

//给日志加上时间戳
trait ConsoleTimeInfo extends ConsoleInfo{
  override def log(msg: String): Unit = super.log(s"${java.time.Instant.now}$msg")
}

//截取一定长度的日志
trait ConsoleShorterInfo extends ConsoleInfo{
  val length:Int = 15
  override def log(msg: String): Unit = {
    super.log(
      if(msg.length <= length)
        msg
      else
        s"${msg.substring(0, length)}"
    )
  }
}

class Account{
  protected var balance:Double = 0.0
}

class SavingAccount extends Account with ConsoleInfo{
  def withdraw(amount: Double): Unit ={
    if(amount>balance) log("hello you are welcome")
    else balance = balance - amount
  }
}

/**
  * 特质可以为类提供可堆叠的改变
  * super方法可以从右往左往上调
  */
object TraitTest {
  def main(args: Array[String]): Unit = {
    val acc = new SavingAccount with ConsoleShorterInfo with ConsoleTimeInfo
    acc.withdraw(20.0)
  }
}
  • 样例类
object CaseClassDemo {
  def main(args: Array[String]): Unit = {
    /**
      * 定义样例类
      * 默认带有apply方法
      * 构造函数的参数默认是public val修饰的
      */
    case class Message(title:String, body:String)

    //创建一个样例类对象
    val message = Message("hello", "world")
    println(message.title+":"+message.body)

    //样例类的比较是基于值进行比较的
    val message1 = Message("hello", "world")
    println(message == message1)

    //样例类的copy
    val message2 = message1.copy()
    //不完全copy
    val message3 = message.copy(title = "hi")
  }
}
模式匹配
  • 基本模式匹配
  val subjects = Array("Hadoop", "Spark", "Flink")
  val subject = subjects(Random.nextInt(subjects.length))

  subject match {
    case "Hadoop" => println("学习Hadoop")
    case "Spark" => println("学习Spark")
    case _ => println("不知道你在学习什么")
  }
  • 加条件模式匹配
  def jdugeGrade(age:Int, grade:Char): Unit = {
    grade match {
      case 'A' => println("you are excellent")
      case 'B' => println("you are grate")
      case 'C' => println("you are good")
      case _ if(age > 18) => println("i don not know how you study")
      case _ => println("you need word harder")
    }
  }
  • Array模式匹配
  def greeting(array:Array[String]): Unit ={
    array match {
      case Array("zhangsan") => println("hello 张三")
      case Array(x,y) => println("hello "+ x +" and "+ y)
      case Array("zhangsan", _*) => println("hello zhangsan and others")
      case _ => println("hello everybody")
    }
  }
  • List模式匹配
  def greeting(list:List[String]): Unit ={
    list match {
      case Nil => println("there are nobody here")
      case "zhangsan"::Nil => println("hello zhangsan")
      case x::y::Nil => println("hello "+ x + " and "+ y)
      case "zhangsan"::tail => println("hello zhangsan and others")
      case _ => println("hello everybody")
    }
  }
  • 类型匹配
  def matchType(obj:Any): Unit ={
    obj match {
      case x: Int => println("Type int")
      case x: Float => println("Type float")
      case x: Map[_, _] => {
        x.keys.foreach(i => {
          println("key: " + i)
          println("value: " + x(i))
        })
      }
      case _ => println("other Type")
    }
  }

  matchType(Map("name"->"zhangsan", "age"->15, "adress"->"广东省广州市"))
  • 异常处理
scala高级函数
  • 字符串高级操作
  /**
    * 字符串连接
    */
  val name = "zhangsan"
  println(s"hello,$name")
/**
    * 多行显示
    * 按三次 shift+‘""’会自动出现
    */
  val sentence =
    """
      |hello
      |hi
      |how are you
    """.stripMargin
  println(sentence)
  • 匿名函数
  val functionA = (x:Int, y:Int) => x+y
  def functionB = (name:String, age:Int) => {
    println(s"my name is $name, I am $age years old")
  }
  println(functionA(2,3))
  functionB("zhangsan", 18)
  • 部分参数函数
  /**
    * 部分参数函数
    */
  //定义一个主函数
  def somebodySay = (somebody:String, word: String) => {
    println(somebody+" : "+word)
  }
  //部分参数函数
  def tomSay = somebodySay("Tom", _:String)
  def marySay = somebodySay("mary", _:String)

  tomSay("hello , mary")
  • 方法的嵌套和多态
/**
    * 方法的嵌套和多态
    */

  //方法嵌套:求阶乘
  def outFun(x: Int): Int ={
    def inFun(x:Int, y: Int): Int ={
      if(x<=1) y
      else inFun(x-1,x*y)
    }
    inFun(x,1)
  }
  println("10的阶乘: "+outFun(10))

  //方法多态:通过类型实现参数化,类似泛型
  def createList[A](x: A, length:Int):List[A] = {
    if(length<1)
      Nil
    else
      x::createList(x, length-1)
  }
  println(createList[Int](4,10))
高阶函数*
  • map
  /**
    * map:逐个去操作集合中的元素
    */
  val array = Array(1, 2, 3, 4, 5)
  array.map(x => x*2).foreach(println)
  array.map(_ + 2).foreach(println)
  • filter
  /**
    * filter:返回符合条件的元素集合
    */
  val list = List(1, 3, 5, 7, 9)
  list.map(x => x+2).filter(x => x>8).foreach(println)
  list.map(_ * 2).filter(_ > 8).foreach(println)
  • reduce和folder
  /**
    * reduce:对集合的元素两两进行操作,默认是Left
    * fold:相较于reduce,多了初始值
    */
  val list = List(2, 4, 6, 8, 10)
  println(list.reduce((x, y) => x + y))
  println(list.reduce(_ - _))
  println(list.reduceRight(_ - _))

  println(list.fold(10)(_ - _))
  • flatten 和 flatmap
  /**
    * flatten:把嵌套的结构打开
    */
  List(List(1,3), List(5,8)).flatten.foreach(println)
  Array("hello", "hi").flatten.foreach(println)
  /**
    * flatMap:结合map和flatten的功能
    */
  List(List("hello","hi"),List("thinks", "good job")).flatMap(_.map(_+", jack")).foreach(println)
scala隐式类
  • 简单使用
  //隐式类的简单引用,把File类隐式转化为RichFile类
  implicit class RichFile(from: File) {
    def read:String = Source.fromFile(from.getPath).mkString
  }

  val content = new File("src/test.txt").read

  println(content)
  • 隐式类
package com.test

object ImplicitClass {
  /**
    * 定义一个隐式类
    * 隐式类只能定义在类、trait、object内部
    * 隐式类的构造函数只能带一个非隐式参数
    */
  implicit class IntWithTimes(x:Int){

    def times[A](f: =>A) = {
      //递归方法需要显式指明返回类型
      def loop(current:Int):Unit = {
        if(current>0){
          f
          loop(current-1)
        }
      }
      loop(x)
    }
  }
}
package com.test
import ImplicitClass._

object ImplicitTest extends App {

  10 times(println("success"))

}
  • 隐式转换函数
  //定义一个隐式转换函数,把double转为Int
  implicit def doubleToInt(x: Double) = x.toInt

  var a: Int = 10
  var b: Double = 10.99

  //加上隐式转换函数之后编译通过,编译器会自动寻找合适的隐式转换函数
  a = b
操作外部数据

csdn案例

你可能感兴趣的:(scala入门基础)