Spark之scala

一、什么是scala

scala 是基于JVMde 编程语言。JAVA是运行在jvm上的编程语言,java 源代码通过jvm被编译成class 文件,然后在os上运行class 文件。scala是运行在jvm 上的编程语言,scala源代码通过jvm被编译成class文件,然后在os上运行class文件。

二语法:

1.声明值和变量

var a =12 // 定义变量 vary

val  b = 23//  定义常量:value

2.有趣的语法特性

在scala的变量声明时,可以不指定类型,由解释器自己判断。
    “superman ”*3    //表示字符串“ superman”反复输出3次
    “superman ”*3    //实际上是字符串“ superman”调用方法*,传入的参数是3

3.函数:

函数在声明后,无论是否有“=”,都有返回值。当没有“=”的时候,表示返回值是Unit类型,Unit类型的值是()。当有“=”的时候,返回值是函数体中的最后一行的值。如果返回值类型强制指定为Unit类型,那么返回值必定是()。

4. 判断:

/**
 * 判断if
 */
object Test21 extends App{
    def judge(a:Int) :Int = {
      if(a > 0){
         1    //return相当于函数版的break语句
      }else if(a < 0){
        -1
      }else{
        0
      }
    }
    
    var c = judge(-3)
    println(c)
}
5.循环
/**
 * while 和 for循环
 */
object Test22 extends App{
    /*while循环*/
//  while(true){
//    println("hello")
//  }
  
  
  /*for循环  scala中的for基本形态*/
//  for(int i = 0 ; i < 5 ; i++)  //java的for循环
//  for( i : List)                  //增强for
  
//  println(1 to 10)   //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
//  for(i <- 1 to 10 ){  //闭区间
//    println(i)
//  }
  
//  for(i <- 1 until 10 ){  //开区间
//    println(i)
//  }
  
//   for(i <- 1 until 10 reverse){  //倒序  不能使用 10 to 1
//       println(i)
//   }
   
  /*高级for循环*/
  //守卫
//    for(i <- 1 to 10 reverse ; if i % 3 == 0){
//      println(i)
//    }
  
//      for(i <- 1 to (10,3)){   //改变步长
//      println(i)
//    }
  
//  for(i <- 1 to 10 ; j <- 1 to 5){  //双重for循环
//      println(i + " - " + j)
//  }
  
//  //for的推导式
//  var c = for( i <- 1 to 10 )yield (i * 2)
//  println(c)

6.常用的数据结构

6.1数组

/**
 * 数组
 */
object Test31 extends App{
  /*定长数组*/
  //使用new定义数组
//    var arr1 = new Array[Int](5)
//    arr1(1) = 2
////    println(arr1)
//    for(i <- arr1){
//      println(i)
//    }
  
  //使用Array类进行定义
  var arr2 = Array(1,2,3,4,"hehe")
//  for( i <- arr2){
//    println(i)
//  }
  
//  println(arr2.min)
//  println(arr2.max)
//  println(arr2.sum)
//  println(arr2.mkString("[",",","]"))   //Arrays.toString(arr)  [1,2,3]
  
  /*变长数组*/
//  var arrbuf1 = ArrayBuffer(1,2,3,4)
//  arrbuf1 += 5
//  arrbuf1 -= 3
//  arrbuf1 ++= Array(3,4,5)
//  arrbuf1 --= Array(3,4,5)
//  arrbuf1.toArray
//  println(arrbuf1.mkString(","))
  
//  var arrB = arr2.toBuffer
//  arrB += 9
//  println(arrB.mkString(","))
  
  
  //filter 和 map用法
  var arr4 = Array(1,2,3,4,5)
  var arr5 = arr4.filter( _ % 2 == 0 ).map( _ * 2)
  println(arr5.mkString(","))
}
 
6.2映射
**
 * 映射
 */
object Test32 extends App{
  /*不可变的映射*/
  //(zhangsan,18)键值对称作对偶   用()表示
    var map1 = Map[String,Int](("zhangsan" , 18) ,( "lisi" , 19))
    map1 += ("wangwu" -> 80)
//    map1("zhangsan") = 12
    map1 += ("zhangsan" -> 20)
//    println(map1("zhangsan"))
//    for(i <- map1){
//      println(i)
//    }
    
//    if(map1.contains("zhaoliu"))
//    println(map1("zhaoliu"))
    
    
    /*可变的映射*/
//    var mapB = scala.collection.mutable.Map[String,Int]("zhangsan"->20,"lisi"->12)
//    mapB("zhangsan") = 30
//    for(i <- mapB){
//      println(i)
//    }
    
    
    /*与java的互操作*/
//    var list = new ArrayList[Int]
//    list.add(1)
//    list.add(2)
//    
//    for(i <- 0 to list.size() - 1 ){
//      println(list.get(i))
//    }
    
    /*map其他遍历方式*/
    
//    for((k,v) <- map1){  //方式一
//      println(k + "->" + v)
//    }
    
    //方式二
    var set1 = map1.keys 
    var set2 = map1.keySet 
    for(i <- set1){
      println(map1(i))
    }
//    println(set2)
6.3元祖
 
/**
 * 元组
 */
object Test33 extends App{
  
  //元组定义
  //对偶(使用“()”表示)只是元组最简单的形式  使用()表示
    var t = (1,2,3,4)
//    for(i <- t){   //元组不能使用for遍历
//      println(i)
//    }
    
//    println(t _3)   //元组的下标从1开始
//    println(t _1)   //元组的下标从1开始
    
    var (first,second,third,forth) = t
//    var (first,second,third,_) = t
//    println(second)
    
    var s = "Hello World!"
//    println(s.partition(_.isUpper))
    
    
    //拉链操作
    var arr1 = Array(1,2,3,4,5,6)
    var arr2 = Array("a","b","c","d","e")
    var arr3 = arr1.zip(arr2)   //
//    for(i <- arr3){
//      println(i)
//    }
    println(arr3.mkString(","))
    var map = arr3.toMap   //map
    for(i <- map){
      println(i)
    }
    

7.类

类的定义 : 使用class定义

类的字段:在类中使用var,val定义字段

类的方法:scala中,使用var定义字段默认提供setter和geter方法,对应的名称为value_= 和value.

/**
 * 类的基本内容
 */

class TestClass41{
//   @BeanProperty var monary = 100
  var monary = 100
   
//   def show {
//     println("hello")
//   }
}


object Test41 extends App{
  
    var a = new TestClass41()  //实例化一个类
    a.monary = 200
    println(a.monary)
//    println(a.show)
    
    //scala使用var定义字段 默认生成对应的setter和getter方法  对应的名称monary_= 和 monary
    
//    a setMonary 300
//    println(a getMonary)
    
    //使用val定义字段的时候  scala不在提供setter方法
    
    //@BeanProperty和private不能同时共用
    
    
}
 
/**
 * 类的基本内容2
 */
class TestClass42{
  private var monary = 0
  
  def setMonary(a:Int){  //自定义setter方法
    if(a > 0)
    this.monary = a
  }
  
  def getMonary = {  //自定义getter方法
    this.monary
  }
  
}

object Test42 extends App{
    var c = new TestClass42
    c setMonary -1000
    println(c getMonary)
    
}
构造器:
/**
 * 类的构造器
 */
//class TestClass43(var name:String = "xxx" , var age:Int = 0) {  //主构造器  带参数称为默认值
//  
////  var name:String       //需要初始化
////  var age:Int 
////  public TestClass43 {}   //java的构造器写法
//  println("name=" + name)
//  println("age=" + age)
//  
//}

class TestClass43 {  //辅助构造器 
  var name:String = "lisi"      //需要初始化
  var age:Int = 0
  
  def this(name:String ){
    this()        //辅助构造器第一行要调用主构造器
    this.name = name
    println("第一个辅助构造器")
  }
  
  def this(name:String ,age:Int){
    this(name)    //还可以调用其他辅助构造器
    this.name = name
    this.age = age
    println("第二个辅助构造器")
  }
   
  println("name=" + name + " age=" + age)
  
  def show = {
    "name!=" + name + " age!=" + age
  }
}


object Test43 extends App{
    var c = new TestClass43("wangwu",90)
//    println("name=" + c.name)
//    println("age=" + c.age)
    
    println(c.show)
    
    
}
 
 
8.对象
定义:Object是一种类型,与class非常相似。
Object可以提供java中的静态字段、静态方法的功能。
 
伴生对象
/**
 * 伴生对象
 */

class TestObject51 {
  private var value = 10
  def display{
    println(TestObject51.value)
  }
  
  def show(a:TestObject51){  //自定义getter方法
    this.value =  TestObject51.value
  }
}

/*伴生对象*/
object TestObject51{    //对象使用object定义
  //该对象作为同名类的伴生对象
//  private[this] var value = 10
  private var value = 10
  
  private def show {
    println("超人")
  }
}

object Test51 extends App{
  
//    println(TestObject51.value)  //不能访问对象中的私有字段
//    println(TestObject51.show)
    
}
 
 
apply 方法:
f(arg1,arg2,**)是函数调用方法,用着非常好用,如果f是类的实例,相当于调用类的apply()方法。
/**
 * apply方法
 */

object Test52 extends App{
//    var arr = new Array[Int](5)
    var arr = Array.apply(1,2,3,4)  //构造数组使用的是apply方法
    
    var map = Map.apply[String,Int]("zhangsan"->12)
    
}
 
9.高阶函数
1.函数可以赋给变量值
首先,在scala中,函数是一等公民
2.匿名函数:
函数的形式是(形参列表)=>返回值类型
var ff = (s: string) => s.toUpperCase
println(ff)
/**
 * 高阶函数
 */

object Test61 extends App{
    //函数定义
    def add(a:Int ,b:Int) = {
      a + b
    }
//    var c = add(1,2)
//    println(c)
    
    var func1 = add _     //把一个函数的实现传递给另外一个函数 
//    println(func1(1,2))
    
//    var func2 = (x :Int) =>  x + 3 //传递一个匿名函数给给一个变量
//    var func3 = (x :Int) =>  {x + 3} //传递一个匿名函数给给一个变量
//    var func4 = (x :Int) =>  (x + 3) //传递一个匿名函数给给一个变量
    
//    for(i <- arr)  
//    Map[String,Int]("zhangsan" -> 12)
//    println(func2(3))
    
//    def func5(a:Int ,f:(Int)=>(Int)) = {
//      f(a) + 1
//    }
//    println(func5(4,(x:Int) => {x + 2}))   //传递一个匿名函数给该函数
    
    //调用函数封装举例
//    def CPU(a:Int) = {
//      a * 8
//    }
//    def GPU(a:Int) = {
//      a + 9
//    }
//    def compute(men:Int,CPU:(Int)=>(Int),GPU:(Int)=>(Int)) = {
//      men + CPU(2) + GPU(2) 
//    }
//    println(compute(4,CPU,GPU))
    
    def func6(f:(Int)=>(Int)) = {
      f(1)
    }
//    println(func6(_ + 2))  //简写条件:1.只有一行代码   2.只有一个形参  3.把匿名函数作为形参
//    println(func6(_ + _))  
    
    //总结“_”  :
//    1.代表数组每一个元素
//    2.指的是传递是确切的一个函数 而不是忘记给该函数传递参数
//    3.元组的元素取值    
    
    //思考题
//    def func7 (x :Int ,y:Int) = {
//      (y : Int) => {
//          x + y
//        } + 2
//    }
//    println(func7(3,4)(2))
    
    //一些有用的函数 map foreach reduceLeft 
//    (1 to 9).map("*" * _).foreach(println _)
    
    var c = (1 to 3).reduceLeft(_ + _)   //1 + 2 + 3
    println(c) 
    
}
 
 
3. 函数作为形参(demo 同上)
1223

对于只有一个参数的,可以只写函数体。

fun3(a=>a+2)

如果形参只有一个,可以在函数体中使用_代替。

fun3(_+2)

函数作为形参的终极版本。

4.把匿名函数放在函数体内
图片1
5.一些有用的高阶函数
图片2
 
10.继承:

抽象类
    1.抽象类不一定有抽象字段,有抽象字段或者抽象方法的类一定是抽象类,只需要添加abstract关键字
    2.有抽象字段一定是是抽象类(scala中字段定义时一定要初始化)
    3.重写字段时实质就是在重写字段的setter/getter方法
   

覆盖方法
    非抽象类覆盖方法的时候,一定使用override。

覆盖字段
      抽象字段一定要有类型描述。
      覆盖的时候,一定使用override。

/**
 * 继承--抽象类
 */

abstract class Person {
  //抽象类不一定有抽象字段或者抽象方法
  //有抽象字段或者抽象方法的类  一定是抽象类
  var name:String  
  val age:Int
  def story:String
}

//方式一
//class Student extends Person{  //覆盖字段时实质上是覆盖了字段setter、getter方法
//  var name:String = "Jeckson"  //var定义的字段只能使用var覆盖,并且var覆盖只能是为实现的字段 
//  val age:Int = 20        //使用val定义的字段只能使用val覆盖 
////  def story = "dance"     //
//  def story = "dance"     //使用def定义的抽象方法可以使用def覆盖也可以使用val ,当def为无参时函数可以使用val
//}

//方式二
//class Student (var name:String = "Jeckson" ,val age:Int = 20 ,val story:String = "dance") extends Person 


object Test71 extends App{
//  var c = new Student
//  println(c.name)
//  println(c.age)
//  println(c.story)
  
  var c = new Person {  //方式三  匿名子类
      var name:String = "Jeckson"  //var定义的字段只能使用var覆盖,并且var覆盖只能是为实现的字段 
      val age:Int = 20        //使用val定义的字段只能使用val覆盖 
      def story = "dance"     //
  }
}

匿名子类重写超类

图片3

抽象字段和抽象方法

12

/**
 * 构造顺序
 */
class Person1 {
  val age:Int = 10
  var arr:Array[Int] = new Array[Int](age)  //调age字段的getter方法
}

//class student1 extends Person1{
//  override lazy val age:Int = 18   //如果覆盖的父类不是抽象类  必须要写override
//}

class student1 extends { //解决办法③
  override val age:Int = 18   //如果覆盖的父类不是抽象类  必须要写override
} with Person1

//特质
/*trait student2 {
  var a:Int = 10
  var b:Int
}
trait student3{
  def show = "123"
}
class student4 extends student2 with student3{
  var b:Int = 1
}*/

object Test72 extends App{
    var c = new student1
    println(c.age)
    println(c.arr.length)  
    //输出18 0   解决办法:1.字段前面添加final  2.字段前面添加lazy  3.解决办法③
    //原因:
//      a.主构造器和class类交织在一起
//      b.子类中使用了override覆盖超类中的字段,构造子类时超类的字段值会被覆盖
//      c.student1类作为student1的主构造器,调用了超类的Person1的主构造器
//      d.首先,构造器将age值设置为10
//      e.接着代码往下走,为了初始化arr数组,调用了age的getter方法
//      f.而age字段被重写了,也就是说getter方法被重写了
//      g.被重写的getter方法还没有被初始化,确切说就是字段age还是对象在被分配空间时所有整型字段的初始值
//      h.arr数组长度被设置为0
//      i.子类Student1类构造器执行,age被赋值为18
}

10 .模式匹配

更好的switch case

12

object Test73 extends App{
//    var t = (1,2,3)
//    var (first,second,third) = t   //模式匹配
//    println(first)
    
    var s = "++"
      
    var result = s match {
      case "a" => println("超人")
      case "*" =>  1
      case "牛人" => "superman"
      case _ if s.contains("=") => (x:Int) => {x + 1} 
      case _ => 0
    }
    
    println(result)
}

仅此献给努力的你我。

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/chaoren399/p/4757782.html