Scala 小记

默认值:

var a:String = _    (是var,不是val,会报错。结果:null)
var b:Boolean = _   (false)
var d:Double = _    (0.0)
var i:Int =_        (0)

构造器/构造函数

主构造器是直接定义在类名后面,主构造器中的参数最终会被编译成字段/属性
(不带val或者var的参数其实是private的,自己调用没问题)

class ConstructorExtendsApp {

}

/**
  * 构造器/构造函数(不带val或者var的参数其实是private的,自己调用没问题)
  * 主构造器是直接定义在类名后面,主构造器中的参数最终会被编译成字段/属性
  */
//java 重载(自己的方法修改,重写:父方法的修改) (ps:override和overwrite的区别)
class Person(val name:String, val age:Int){
  println("Person constructor enter...")
  val school = "dfd"
  var gender:String = _
  
  def tt(): Unit ={
    println("haha")
  }

  /**
    * 附属构造器
    * 语法: def this(....)
    * 第一行代码:必须要调用已经存在的主构造器或者其他附属构造器
    */
  def this(name:String, age:Int, gender:String){
    this(name,age)
    this.gender = gender
  }
  
  println("Person constructor leave...")
  
  tt()
  
}

/**
  * 子类构造方法触发之前要先触发其父类的构造方法
  * 父类已有的字段就不需要使用val/var修饰(是不是私有的问题)
  */
class Student(name:String, age:Int, val major:String) extends Person(name,age){
  println("Student constructor enter...")

  override val school: String = "777"
  //override def toString = "this is Student toString"
  
  println("Student constructor leave...")
}


object ConstructorExtendsApp extends App{
//  继承了App类,就可以不需要main方法
//  val person = new Person("dds",2)
//  println(person.name + ":" + person.age)
//  person.tt()
//  
//  val person2 = new Person("sdsds",23,"666")
//  println(person2.gender)
  
  val student = new Student("xiaow", 20, "huaxue")
  println(student.toString)
  println(student.school)
}

object类自带的方法有,hashCode,equals,clone(Creates and returns a copy of this object.),toString,notify,notifyAll,wait,finalize (这些面试可能问)

/**
  * class名字和object名字相同
  *  class就叫做object的伴生类
  *  object就叫做class的伴生对象(调用object不需要new,相当于Java的静态类)
  *  Java中,单例模式指的是使用静态方法来调用私有参数,这样外界调用方法时不用实例化。
  */
class ObjectApp {

}

class ApplyTest{
  def test(): Unit ={
    println("class test")
  }

  def apply() ={
    println("class apply....")
  }
}

object ApplyTest{
  println("object enter...")

  def apply() ={
    println("object apply....")
    new ApplyTest
  }
  //等价于下面
  //def apply(): ApplyTest = new ApplyTest()
  
  
  var count = 0
  def static(): Unit ={
    println("object static...")
  }
  def countSum() {
    count += 1
  }
  println("object leave...")
}

object Timer {
  var count = 0
  def countSum(): Long ={
    count += 1
    count
  }
}

object ObjectApp extends App {

  ApplyTest.static()
  //相当于先实例化再执行,所以enter和leave先执行,在执行static()
  
//  for (i<- 1 to 10){
//    ApplyTest.countSum()
//  }
//  println(ApplyTest.count)
//  
//  val a = new ApplyTest()
//  a.test()
  //伴生对象后面加() ==> 其实调用的是伴生对象的apply的方法 <== 定义的
  //优点是直接用就可以,不用new class了
  val b = ApplyTest()
  b.test()
  println(b)
  b()
  
//  val c = new ApplyTest()
//  println(c)
//  c()
  /**
    * 类名()(类名加上一个括号) ==> object apply
    * new出来的对象()(new出来的对象加上一个括号) ==> class apply
    */
  
  
  
  val aa = new Array[String](5)
  val bb = Array("hadoop","spark","hive")
  val cc = scala.collection.mutable.ArrayBuffer[Int](3)
  
}

其实
val a = Array(“sds”,“sd”)使用的就是object的apply方法(没有new,而且Array后面有括号)

10.mkString变成字符串

集合

Array 定长
ArrayBuffer 变长

Nil 是一个空list
List 定长
ListBuffer 变长

scala> Nil
res8: scala.collection.immutable.Nil.type = List()

scala> val l = List(1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)

scala> l.head
res9: Int = 1

scala> l.tail
res10: List[Int] = List(2, 3, 4, 5)

scala> val l2 = 1 :: Nil
l2: List[Int] = List(1)

scala> val l3 = 2 :: l2
l3: List[Int] = List(2, 1)

同样对于ListBuffer来说,可以使用+=(后可接元组,也可是单个的值),++=(后接List),-=(减的是具体的值,而不是下标),–=(减的是具体的值)
toArray,toList等方法也可用

Set …和list差不多

Map
键值对,取值直接用key
定义:val a = Map(“asd”->10)
取值:a(“asd”)

如果定义的是HashMap(可变长里面的,map不知能不能用)
为空的话,取值的时候是会报错的,因为没有这个key,可以使用c.getOrElse(“asd”,-1)来取值。

def getOrElse[B1 >: B](key: A, default: => B1): B1 = get(key) match {
case Some(v) => v
case None => default
} 

Some:  final case class Some[+A](x: A) extends Option[A]
None:  case object None extends Option[Nothing]

所以m.get(1)得到的是Option[Int],需要再加一个get或者getOrElse才行
m.get(1).get 或者 m.get(1).getOrElse(“null”)

map的迭代:

val m = scala.collection.mutable.HashMap[String,Int]()
m += ("a"->3,"b"->4)

for((key,value) <- m){
	println(key + " : " + value)
}
//keySet是一个都是key的集合
for(key <- m.keySet){
	println(key + " : " + m.getOrElse(key, 0))
}

for(value <- m.values){
	println(value)
}

for((key,_) <- m){
	println(key + " : " + m.getOrElse(key, 0))
}

接口 interface (Java中的)
Trait(Scala中的,和Java中类似)

模式匹配

java: swich case  根据不同的条件走不同的分支
只能匹配值
类型、Array、List.. case class

变量 match {
	case 值 => 代码
	case 值 => 代码
	case 值 => 代码
	....
	case _ => 代码
}

  def judgeGrade2(name:String, grade:String): Unit = {
    grade match {
      case "A"=>println("prefect")
      case "B"=>println("good")
      case "C"=>println("just so so")
      case _ if name == "666" =>println(name + " you are a good boy")
      case _ => println("12121212")
    }
  }

  def greeting(list: List[String]): Unit ={
    list match {
      case "dove"::Nil => println("Hi: 德芙")
      case x::y::Nil => println("Hi: " + x + " , " + y)
      case "xiaoweiba"::tail => println("Hi: xiaoweiba and other friends")
      case _ => println("Hi: all")
    }
  }

  def greeting(array: Array[String]): Unit ={
    array match {
        //dove开头的且只有一个元素
      case Array("dove") => println("Hi: 德芙")
        //2个任意元素
      case Array(x,y) => println("Hello:" + x + "," + y)
        //xiaoweiba开头的任意多个元素
      case Array("xiaoweiba", _*) => println("Hello: zhangsan and other")
        //大于等于3个元素,且不以xiaoweiba开头
      case _ => println("Hi: everybody")
    }
  }

//Any是一个顶层的数据类型
  def matchType(obj:Any): Unit ={
    obj match {
      case x:Int => println("int")
      case s:String => println("string")
      case m:Map[_,_] => m.foreach(println)
      case _ => println("other type")
    }
  }

之后的调用可以适用任何情况

异常处理(IO的步骤)

  //IO常见处理步骤
  try {
    //1) open file
    //2) use file
    val i = 1/0
  } catch {
    case e:ArithmeticException => println("除数不能为0")
    case e:Exception => println("错误的地方/原因为:" + e.getMessage)
  } finally {
    //io file(io的关闭)
    println("finally")
  }

case class(不用new就可以直接使用,在Spark SQL中用的比较多)

class Person
case class CTO(name:String, floor:String) extends Person
case class Employee(name:String, floor:String) extends Person
case class Other(name:String) extends Person

  def judgeIdentify(person:Person): Unit ={
    person match {
        //可以直接    case 子类
      case CTO(name,floor) => println("cto")
      case Employee(name,floor)=>println("Employee")
      case _ => println("Other")
    }
  }

  //是个方法,可以调用
  judgeIdentify(CTO("dove","3"))
  judgeIdentify(Other("Other"))

高阶函数 *****

一个函数是可以赋值给一个常量的,不过赋值的时候函数名要加" _"或者"(_)"
  def sayHello(name:String): Unit ={
    println("Hello:" + name)
  }
val sayHelloFunc = sayHello _
val sayHelloFunc = sayHello(_)
高阶函数map,reduce,fold…
  val l = List(1,2,3,4,5,6,7,8)
  //所有元素乘以2, map:把l里面的每个元素都做一个相同的操作1ll1
  l.map((x:Int) => x*2)
  //参数的类型推断机制,可以省略类型
  l.map((x) => x*2)
  l.map(x => x*2)
  l.map(_*2)
  //以上四个的结果相同
  l.map(_*2).filter(_>8)//_ 代表每个元素,取大于8的
  
  l.take(4)//取前四个
  
  //reduce:对元素x和元素y进行处理,使用后面的方法(即x+y)进行处理,以此类推,最后结果是所有元素的和
  l.reduce((x, y)=>x+y)
  l.reduce(_ + _)//l.reduce(_ - _)
  
  //打印出来就能看到详细内容
  l.reduce((x,y) =>{
    println(x + " , " + y)
    x-y
  })

//reduceLeft和reduce类似,reduceRight是从右往左减,第一步:(7-8),下一步:(6-(-1)) ...

  l.max  //8
  l.min  //1
  l.sum  //36
//求大于3的个数
  l.count(x => x>3)
  l.count(_>3)

  val f = List(List(1,2),List(3,4),List(5,6))
  f.flatten //这个是一个算子,把f里面的所有元素扁平化,结果List(1,2,3,4,5,6)
  f.flatMap(_.map(_*2))     //等于map+flatten

匿名函数

(x:Int) => x+1(只有一个参数的话,括号可以省略,但是需要在外面加大括号)
{x:Int => x+1}
所以可以def add = (x:Int,y:Int) => x+y这样用

(x:Int) => x+1相当于y = f(x),x是入参,y是出参,对应的,x:Int是入参,x+1是出参

currying函数

  //currying函数(柯里化)
  def sum(a:Int, b:Int) = a+b  //正常函数
  def sum2(a:Int)(b:Int) = a+b
  println(sum(1,2))
  println(sum2(1)(2))     // Spark SQL UDF函数重点使用

偏函数 PartialFunction

  val array = Array("111","222","333")
  val name = array(Random.nextInt(array.length))
  
  def sayChineseName(name:String):String = name match {
    case "111" => "111"
    case "222" => "222"
    case _ => "333"
  }
  
  println(sayChineseName("222"))
  
  //被包在花括号内没有match的一组case语句 ==> 偏函数
  def sayChineseName2: PartialFunction[String, String] = {
    case "111" => "111"
    case "222" => "222"
    case _ => "333"
  }

  println(sayChineseName2("222"))

字符串使用(源码里面用的比较多)

  val name = "dove"
  println("My name is : " + name)
  println(s"My name is : $name")//带个s,因为里面用到了$
  
//多行字符串
  val b =
    """
      |zheshiyige
      |duohang
      |hallo
      |haha
      |333
    """.stripMargin
  
  println(b)

隐式转换

如何在一个已存在的类中添加一个方法(不许修改源代码/)
File中给我添加一个read方法
Java中可以使用动态代理,而Scala中可以使用隐式转换

implicit def file2RichFile(file:File) :RichFile = new RichFile(file)
val file = new File("C:\\Users\\sky\\Desktop/test.py")
val files = file.read()
//aa是一个迭代器
for (i <- files){
  print(i)
}

class RichFile(val file: File){
  def read() = Source.fromFile(file.getPath)
}

目的:隐式(偷偷摸摸)的对类的方法进行增强

核心:定义我们的隐式转换函数(implicit def xxxx)

object ImplictApp {

  def main(args: Array[String]): Unit = {
    
//定义隐式转换即可,Scala会自动使用
  implicit def man2superman(man: Man):SuperMan = new SuperMan(man.name)

  val man = new Man("dove")
  man.fly()
  }
}


class Man(val name:String)
class SuperMan(val name:String){
  def fly(): Unit ={
    println(s"SuperMan $name fly")
  }
}

一般都会把隐式转换放到一个单独的文件中,在需要的地方import

隐式参数
object ImplictParamApp extends App {

  def testParam(implicit name:String): Unit ={
    println(name)
  }
  
  testParam("aaa")
  implicit val name = "gfgf"
  testParam  //会直接使用定义好的隐式参数
  testParam("ssdsd")
  //变量名随意,但不能有多个隐式参数,如果在main方法外面定义隐式参数,在里面的调用,也可以获取到值(作用域)。
  implicit val s1 = "s1"
  implicit val s2 = "s2"
//  testParam
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值