Scala基础

本文详细介绍了Scala编程语言的特性,包括基于JVM的运行环境、类型推测、并发和分布式模型(Actor)、Trait、模式匹配、高阶函数等核心概念。同时,讲解了Scala的基础语法,如变量定义、数据类型、类与对象、方法与函数、字符串和集合、 Trait、模式匹配以及隐式转换。通过示例代码展示了如何在Scala中实现各种功能,帮助读者深入理解Scala编程。
摘要由CSDN通过智能技术生成

学习视频:https://www.bilibili.com/video/BV1oJ411m7z3
Scala是一种多范式编程语言,设计初衷是集成面向对象编程函数式编程的各种特性

Scal特性

基于JVM
  • 运行在jvm之上,可以和java混编;
  • scala可以调用java的包,Java也可以调用Scala的包
类型推测
  • 不需要显式的定义变量的是数据类型,可以自动推测出来

  • var a = 100;
    val b = 200.0;
    
  • var 定义变量,val定义常量

并发和分布式
  • 使用Actor作为其并发模型。Actor是一种类似于线程的实体
Trait(特性)
  • 类似于java中 interface 和 类 的结合
  • 综合了接口的灵活性和类的强大功能
模式匹配
  • 类似于 switch case,只不过功能更加强大
高阶函数
  • 操作其他函数的函数
  • 甚至可以用其他函数作为当前函数的参数或输出结果

Scala基础

基本语法
  • 定义常量使用 val,定义变量使用 var

  • 每行后面可以不写分号

  • 大小写敏感

  • 类名首字母大写,方法名首字母小写

  • s"$i * $j =" + i * j"

    /*
       for
        */
       val r = (1 to 10)     //1 --10
       val r1 = 1 until  10 //1 --9
       for (i <- 1 to 10){
         println(i)
       }
     
       /*
       if else
        */
       val i = 50
       if (i<30){
         println("i<30")
       }else if(i>30&&i<60){
         println("i<30 && i<60")
       }else{
         println("i>60")
       }
     
       //打印99乘法表
       //    for (i <- 1.until(10)){
       //      for (j <- 1.until(10)){
       //        if(i>=j){
       //          print(s"$i * $j ="+i*j+"\t")
       //        }
       //        if(i==j){
       //          println()
       //        }
       //      }
       //    }
     
       for (i <- 1.until(10);j <- 1.until(10)) {
         if (i >= j) {
           print(s"$i * $j =" + i * j + "\t")
         }
         if (i == j) {
           println()
         }
       }
    
数据类型
Byte一个字节 -128 --127
Short两个字节
Int四个字节
Long八个字节
Float32位单精度浮点型
Double64位双精度浮点型
Char两个字节字符
Booleantrue、false
Unit表示无值,和void等同
String字符串
Null空值或者空引用
Nothing其他所有类型的子类,由于scala会类型推测,当无法推测时就判定为Nothing
Any其他所有类型的父类
AnyRef所有引用类型的父类
AnyVal所有值类型的父类(前9项,String之前)

以上数据类型都是封装后的对象,首字母全部大写

image-20210127183939882

NullTrait,唯一实例是null,是AnyRef的子类
NothingTrait,所有类型的子类,没有实例
NoneOption的两个子类之一,用于安全的函数返回值
Unit无返回值的函数类型(等同于java中的void)
Nil长度为0的list
类和对象
对象
  • 对象object,相当于类的单例对象,不需要使用new实例化。

  • 其中定义的默认都是静态的。所以其中可以直接写main方法。

  • 对象中的构造器会在第一次使用时会被执行,如果一个对象从未被调用,他的构造器也不会执行。

  • object不能传递参数;如果非要传参,需要在其中使用apply方法

    object Test{
      def apply(i: Int) = {
        println("i is:"+i)
      }
      def sout(): Unit ={
        println("test")
      }
    }		
    
  • 类class,需要使用new来实例化。

  • 可以传参,传参一定要指定类型,有了参数就默认有构造函数,类中的属性默认有了getter、setter方法。

  • 而且类中可以直接写执行代码(不需要在外层封装方法)(println)。

  • 类构造的时候,除了方法不执行(构造方法除外),其他都执行

  • 类中的属性可以用private修饰,表示为私有属性

  • 在同一个scala文件中,class名称与object名称一样时,这个类叫做对象的伴生类,对象叫做类的伴生对象。他们之间可以互相访问私有变量

    //重写构造this(),构造中的第一行必须调用默认构造 this()
    class Person(xname:String,xage:Int){
      var name = xname
      val age = xage
      var gender = 'M'
    
      println(name)
        
      def this(yname:String,yage:Int,ygender:Char){
        this(yname,yage)
        gender = ygender
      }
      def sout(): Unit ={
        println(name,age)
      }
    }
    //object中是静态的,所以可以写main函数
    object HelloWorld {
      def main(args: Array[String]): Unit = {
        val person = new Person("zhangsan", 18)
        person.name="lisi"
        person.sout()
        Test(5)
        println("hello world!")
      }
    }
    

方法与函数

方法定义
def max(a:Int,b:Int): Int ={
    if(a>b){
     return a
    }else{
     return b
    }
 }

def max(a:Int,b:Int)={
    if(a>b){
     a
    }else{
      b
    }
}

def min(a:Int,b:Int) = if(a>b) b else a
  • 定义方法使用 def关键字,格式def 方法名(参数列表:类型):返回值类型={方法体}
  • 方法体中最后返回值可以使用return,如果使用return,返回类型一定要指定
  • 如果方法体中没有 return ,默认将方法体中最后一行计算的结果返回,返回类型可以省略
  • 方法体如果可以一行解决,{...}可以去掉
  • 如果定义方法时,方法名和方法体之间的=被省略了,方法最后会返回空值 unit
递归方法
def func(a:Int): Int ={
    if(a==1){
      a
    }else{
      a*func(a-1)
    }
}
  • 递归方法要显式的指明返回类型
默认值参数的方法
//定义
def add(a:Int=10,b:Int=20)={
    a+b
}
//调用
add()
add(100, 200)
add(100)
add(b=100) //只修改某个参数
  • 在参数列表中给定初值
变长参数方法
def func(s:String*)={
    println(s)
}
func("hello","a","b")
  • 在参数列表类型后面加上*,Int* String*
匿名函数
  • ()=>{} 形式出现的就叫匿名函数,不需要函数名
  • 只要出现 => ,就是匿名函数
  • 多用于方法的参数是函数时
def func(s:String*)={
    s.foreach(el => println(el))
}
def fun =(a:Int,b:Int)=>{a+b}
高阶函数
  • 方法参数是函数、方法返回是函数或者两者都是函数,的方法叫做高阶函数
//1. 参数是函数
def fun(a:Int,b:Int)={
    a+b
}
def func(f:(Int,Int)=>Int,s:String)={
    val i = f(100, 200)
    s"$i+$s"
}
//调用
func(fun,"hello")
func((a:Int,b:Int)=>a*b,"hello")

//2.返回是函数
//显式声明返回类型是函数
def func(s:String):(String,String)=>String={
     def fun(a:String,b:String): String ={
       s+a+b
     }
    fun
}
//不显式声明返回类型
def func(s:String)={
     def fun(a:String,b:String): String ={
       s+a+b
     }
    //加个下划线表示 将方法转成函数
    fun _
}
//调用
func("he")("ll","o")

//3. 两者都是函数
def func(f:(Int,Int)=>Int):(String,String)=>String = {
    val i = f(1, 2)
    def fun(a:String,b:String):String={
      s"$i + a + b"
    }
    fun
}
func((a,b)=>a+b)("hello","word")

方法加个下划线表示可以强制将方法转成函数

  def add(a:Int=10,b:Int=20)={
    a+b
  }
  val function1: (Int, Int) => Int = add _
柯里化函数
  def func(a:Int,b:Int)(c:Int,d:Int) = {
    a+b+c+d
  }
 func(1,2)(3,4)
  • 高阶函数三的简化版,隐式转换时要用

字符串和集合

字符串String

String即为java中的String,只是增添了有一些方法

String a = "abcde"
String b = "ABCDEF"
//忽略大小写是否相等
a.equalsIgnoreCase(b)
数组Array
val arr = Array[String]("a","b","c")
//定义长度为3的数组arr1
val arr1 = new Array[Int](3)
arr1(0) = 2;
//打印
arr.foreach(elem=>println(elem))
arr.foreach(println(_))
arr1.foreach(println)

//可变长数组
var arr2 = ArrayBuffer[Int](1,2,3)
//  append 等同于  += ,都是从后面追加
arr2.append(6)
arr2.+=(7)
//  +=: 则是在前面追加
arr2.+=:(8)
arr2.foreach(println)
列表List
val list = List[String]("hello world","hello scala")

//map方法 进一条数据输出一条数据
//输出数据类型为 List[Array[String]]
val value1: List[Array[String]] = list.map(s => {
    s.split(" ")
})
value1.foreach(s => s.foreach(println))

//flatmap方法 进一条数据输出多条数据
//输出数据类型为 List[String]
val value2: List[String] = list.flatMap(s => {
    s.split(" ")
})
value2.foreach(println)

//filter方法,过滤器,匹配上了就保留,否则舍弃
val value3: List[String] = list.filter(s => {
    "hello world".equals(s)
})
value3.foreach(println)

//可变长列表list
var list2 = ListBuffer[Int](1,2,3)
//  append 等同于  += ,都是从后面追加
list2.append(6)
list2.+=(7)
//  +=: 则是在前面追加
list2.+=:(8)
list2.foreach(println)
集合Set
val set = Set[Int](1,2,3,4)
//无序,去重
set.foreach(println)

val set1 = Set[Int](3,4,5,6)
// 并集
set.concat(set1).foreach(println)
//交集
set.intersect(set1).foreach(println)
//差集
set.diff(set1).foreach(println)

//可变set
//import scala.collection.mutable.Set
//val set2 = Set[Int](1,2,3)
import scala.collection.mutable
val set2 = mutable.Set[Int](1,2,3)
set2.add(5)
set2.foreach(println)

//import scala.collection.immutable
//不可变
val set3 = immutable.Set[Int](1,2,3)
set3.foreach(println)
Map
val map = Map[String, Int]("a" -> 100, "b" -> 200, "c" -> 300,"e"->500)
val map2 = Map[String,Int](("a",1),("b",2),("c",3),("d",4))
map.foreach(println)

val value1: Option[Int] = map.get("a")
println(value1)
val value2: Option[Int] = map.get("a1")
println(value2)

val keys: Iterable[String] = map.keys
val values: Iterable[Int] = map.values

// map2追加到map中
map.++(map2).foreach(println)
// map追加到map2中
map.++:(map2).foreach(println)

//可变长Map
val map3 = mutable.Map[String,Int](("a",1),("b",2))
map3.put("c",3)

map3.filter(tem=>{
    val key = tem._1
    var value = tem._2
    value >=2
}).foreach(println)
元组Tuple
  • ()中放入一堆元素就叫元组,元素类型可同可不同
  • 元组最多支持22个元素
  • 元组可new可不new,甚至可以直接写在括号中
  • 只有二元元组能翻转swap
val tuple1: Tuple1[String] = new Tuple1("hahha")
val tuple2: (String, Int) = Tuple2("ss", 20)
val tuple4 = (1, "ma", true, 'C')
val tuple10 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

//打印元组
println(tuple4._3)
println(tuple4)
//遍历元组
val iterator: Iterator[Any] = tuple4.productIterator
iterator.foreach(println)

//二元元组的翻转
println(tuple2)
println(tuple2.swap)

Trait

  • Trait 相当于java接口与抽象类的结合体,既可以有方法体的方法,也可以有没有方法体的方法
  • Trait 不能传参
  • 继承第一个 Trait 用extends关键字,后面再继承其他 Trait 用with关键字
trait Listen{
    def listening(name:String)={
        println(s"$name is listening...")
    }
}
trait Speak{
    def speaking(name:String): Unit ={
        println(s"$name is speaking...")
    }
}

class Human(xname:String) extends Speak with Listen {
    val name = xname
}
object TraitTest {
    def main(args: Array[String]): Unit = {
        val human1 = new Human("zhangsan")
        human1.speaking(human1.name);
        human1.listening(human1.name);
    }
}
trait IsEqual{
    def isEqual(o:Any):Boolean
    def isNotEqual(o:Any):Boolean={
        !isEqual(o)
    }
}
class Point(xx:Int,yy:Int) extends IsEqual {
    val x = xx
    val y = yy
    override def isEqual(o: Any): Boolean = {
        o.isInstanceOf[Point] && o.asInstanceOf[Point].x==this.x
    }
}

val point1 = new Point(1,2);
val point2 = new Point(1, 3)
println(point1.isEqual(point2))

模式匹配Match

基础匹配
  • case _ 相当于 default,什么都能匹配上,要放到最后
  • match可以匹配值还可以匹配类型
  • 匹配过程中会有数值的转换
  • 从上往下匹配,匹配上了就自动终止
  • 模式匹配外部的{ }可以省略
object MatchTest {
    def main(args: Array[String]): Unit = {
        val tuple = (1, 2, 1.2, true, 'c', "abc")
        val ite = tuple.productIterator
        //    ite.foreach(i=>{
        //      matchTest(i)
        //    })
        ite.foreach(matchTest)
    }

    def matchTest(o:Any)={
        o match {
            case 1 => println("value is 1")
            case i:Int => println(s"type is Int,value is $i")
            case d:Double =>println(s"type is Double,value is $d")
            case 'c' =>println("value is Char")
            case _ => println("no match ...")
        }
    }
}
偏函数
  • 模式匹配中,只有case没有match,可以将其定义为偏函数
  • 偏函数定义时,不能使用()传参,要使用PartialFunction中传入一个值
  • 函数格式为def 函数名:PartialFunction[输入类型,输出类型] = {case => }
object PartialFun {
    def myTest :PartialFunction[String,Int]={
        case "a" => 1
        case "b" => 2
        case "c" => 3
        case _ => 10
    }

    def main(args: Array[String]): Unit = {
        println(myTest("d"))
        println(myTest("b"))
    }
}
样例类
  • 使用关键字 case修饰的类,就叫做样例类
  • 该类默认实现了getter、setter、toString、equals、 copy、hashCode等方法
  • 样例类可以 new 也可以不 new
case class Animals(sname:String,sage:Int){
    val name = sname
    val age = sage
}
object CaseClass {
    def main(args: Array[String]): Unit = {
        val a1 = Animals("miao", 2)
        println(a1)
        println(a1.hashCode())
    }
}

隐式转换

定义
  • 在Scala编译器进行类型匹配时,如果找不到合适的类型
  • 那么隐式转换会让编译器在作用范围内自动推导出来合适的类型
隐式值与隐式参数
  • 在参数前面加上implicit,就会自动在同一个作用域(同一个类或对象)中查找隐式的同类型的参数
  • 同类型的参数的隐式值只能在作用域中出现一次
  • 如果方法只有一个参数且为隐式参数时,可以直接用implicit定义该参数,调用时直接创建类型不传入参数就可以
  • 如果方法中有部分参数需要隐式转换,那么该方法需要使用柯里化的方式定义,而且隐式参数必须放在第二个括号中
object ImplicitTest {

    def printName(implicit name:String): Unit ={
        println(s"the name is $name")
    }
    //部分参数需要隐式转换
    def printNameAndAge(age:Int)(implicit name:String)={
        println(s"the name is $name,the age is $age")
    }
    def main(args: Array[String]): Unit = {
        implicit val name1 = "zhangsan"
        printName
        printName("lisi")
        printNameAndAge(15)
        printNameAndAge(15)("lisi")
    }
}
隐式转换函数
  • 使用implicit修饰的方法就叫隐式转换函数
  • 假设A类型变量调用了 B方法,但是A类型中没有B方法,但是C类型有B方法;
  • 那么编译器就会在作用域中查找有没有隐式转换函数将A类型转换成C类型,如果有,则A类型可以调用B方法
  • 隐式转换函数只与函数的参数类型和返回类型有关,与函数名称无关,所以作用域中不能有其他相同参数类型和返回类型的隐式转换函数
class Animal(name:String){
  def canFly()={
    println(s"$name can fly")
  }
}
class Bird(xname:String){
  val name = xname
}
object ImplicitFunc {
  implicit def birdToAnimal(b:Bird)={
    new Animal(b.name)
  }
    
  def main(args: Array[String]): Unit = {
    val bird = new Bird("eeee")
    bird.canFly()
  }
}
隐式类
  • 使用implicit定义的类,只能定义在对象、类中
  • 若一个变量A没有某种方法或变量,而这个类A可以调用某些方法或者某些变量时,可以定义一个隐式类,隐式类中定义这些方法或变量,隐式类中传入A即可
  • 隐式类的构造必须只有一个参数,同一作用域中不能出现同类型构造的隐式类
class Bird1(xname:String){
    val name = xname
}

object ImplicitClass {
    implicit class Animal1(b:Bird1){
        def canFly()={
            println(s"${b.name} can fly")
        }
    }

    def main(args: Array[String]): Unit = {
        val b = new Bird1("aaaa")
        b.canFly()
    }
}

WordCount

val conf = new SparkConf().setMaster("local").setAppName("wordCount")
val sc = new SparkContext(conf)

val file = sc.textFile("data/hahah.text")
file.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect().foreach(println)
sc.stop()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值