scala04

scala04课件

作业题

object HomeWorke232424r {
    def main(args: Array[String]): Unit = {
      val d1 = Array(("bj", 28.1), ("sh", 28.7), ("gz", 32.0), ("sz", 33.1))
      val d2 = Array(("bj", 27.3), ("sh", 30.1), ("gz", 33.3))
      val d3 = Array(("bj", 28.2), ("sh", 29.1), ("gz", 32.0), ("sz", 30.5))

      val d4:Array[(String,Double)] = d1++d2++d3

      val groupedData:Map[String,Array[(String,Double)]] = d4.groupBy(_._1)

//      val result:Map[String,Double] = groupedData.mapValues(t=>t.map(_._2).sum/t.length)

      val result:Map[String,(String,Double)] = groupedData.mapValues(t=>t.reduce((a,b)=>("",a._2+b._2)))

      result.foreach(t=>println(t._1,t._2._2.formatted("%.1f")))
    }
}

object homework1{
  def main(args: Array[String]): Unit = {
    val pattern = Pattern.compile("[- ]")
    val lst = List("Id1-The Spark", "Id2-The Hadoop", "Id3-The Spark")
//  flatten flatMap  Array((spark,id1),(the,id1),(the,id2))
    //spark-id1 id3
    //The-id1 id2 id3
    val tupleList:List[(String,String)]=lst.flatMap(t=>{
       val strs:Array[String] = pattern.split(t)
       val tuples:Seq[(String,String)] =  for(e<-1 to strs.length-1)yield (strs(e),strs(0))
       tuples
    })
   val groupedData:Map[String,List[(String,String)]] =  tupleList.groupBy(_._1)

    //The - id1  id2  id3
//    val result:Map[String,String] = groupedData.mapValues(t=>t.map(_._2).mkString(" "))
    val result:Map[String,(String,String)] = groupedData.mapValues(t=>t.reduce((a,b)=>("",a._2+" "+b._2)))
    result.foreach(t=>println(t._1+"-"+t._2._2))
  }
}

 

reduce  reduceLeft  reduceRight

reduce底层使用的是reduceLeft,但是reduce不可以类型不一样reduce中放入的函数,参数返回值类型必须一致,并且这个类型是集合中元素的本泛型或者是父泛型

reduceLeft中函数的参数泛型和返回值的泛型必须保持父子关系,返回值和参数可以不一样,但是必须是父类的关系

scala> var arr = Array(1,2,3,4,5,6,7,8)

arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

 

scala> arr.reduce(_+_)

res0: Int = 36

 

scala> arr.reduceLeft(_+_)

res1: Int = 36

 

scala> arr.reduceRight(_+_)

res2: Int = 36

 

scala> arr.reduce(_-_)

res3: Int = -34

 

scala> arr.reduceLeft(_-_)

res4: Int = -34

 

scala> arr.reduceRight(_-_)

reduceRight的归并顺序是从又向左,但是计算顺序还是左右

 

fold  foldLeft  foldRight归并

scala> var arr = Array(("hello",1),("word",1),("c",1))

arr: Array[(String, Int)] = Array((hello,1), (word,1), (c,1))

 

scala> arr.fold(0)((a,b)=>a+b._2)

<console>:13: error: value _2 is not a member of Any

       arr.fold(0)((a,b)=>a+b._2)

                              ^

 

scala> arr.fold(0)((a,b)=>a+b.asInstanceOf[(String,Int)]._2)

<console>:13: error: type mismatch;

 found   : Int

 required: String

       arr.fold(0)((a,b)=>a+b.asInstanceOf[(String,Int)]._2)

                                                         ^

 

scala> arr.fold(0)((a,b)=>a.asInstanceOf[Int]+b.asInstanceOf[(String,Int)]._2)

res12: Any = 3

 

scala> var arr = Array(1,2,3,4)

arr: Array[Int] = Array(1, 2, 3, 4)

 

scala> var arr1 = Array(arr,arr,arr)

arr1: Array[Array[Int]] = Array(Array(1, 2, 3, 4), Array(1, 2, 3, 4), Array(1, 2, 3, 4))

 

scala> arr1.fold(Array[Int]())((a,b)=>a++b)

res13: Array[Int] = Array(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)

def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)

fold的底层使用的是foldLeft

def foldLeft[B](z: B)(op: (B, A) => B): B = {
  var result = z
  this foreach (x => result = op(result, x))
  result
}

foldLeft的泛型可以是不同的泛型,而且泛型间没有父子关系

scala> arr1.fold(0)((a,b)=>a+b.sum)

<console>:14: error: value sum is not a member of Any

       arr1.fold(0)((a,b)=>a+b.sum)

                               ^

 

scala> arr1.foldLeft(0)((a,b)=>a+b.sum)

res15: Int = 30

 

scala> var arr = Array(("hello",1),("word",1),("c",1))

arr: Array[(String, Int)] = Array((hello,1), (word,1), (c,1))

 

scala> arr.foldLeft(0)((a,b)=>a+b._2)

res16: Int = 3

 

foldRight(0)()

scala> var arr = Array(1,2,3,4,5,6,7)

arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7)

 

scala> arr.foldRight(0)(_-_)

res22: Int = 4

 

scala> arr.foldLeft(0)(_-_)

res23: Int = -28

 

aggregate

聚合方法

def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)

源码中aggregate聚合函数中,第一值是初始化的,第二是聚合函数,第三个没用

底层调用的是foldLeft

scala> arr.aggregate

   def aggregate[B](z: => B)(seqop: (B, Int) => B,combop: (B, B) => B): B

 

scala> arr.aggregate(0)(_+_,_+_)

res24: Int = 28

 

scala> arr.aggregate(0)(_+_,_*_)

res25: Int = 28

 

scala> arr.aggregate(0)(_+_,_/_)

res26: Int = 28

 

scala> arr.aggregate(0)(_+_,Null)

<console>:13: error: not found: value Null

       arr.aggregate(0)(_+_,Null)

                            ^

 

scala> arr.aggregate(0)(_+_,null)

res28: Int = 28

aggregate是聚合函数其中第二个聚合函数在spark中有意义,在spark中第二个函数是全局聚合的含义

 

Take方法

scala> var arr = Array(1,2,3,4,5,6,7,8)

arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

 

scala> arr.take(3)

res29: Array[Int] = Array(1, 2, 3)

 

scala> arr.take(4)

res30: Array[Int] = Array(1, 2, 3, 4)

 

slice切分集合

scala> arr

res31: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

 

scala> arr.slice(0,3)

res32: Array[Int] = Array(1, 2, 3)

 

scala> arr.slice(5,3)

res33: Array[Int] = Array()

 

scala> arr.slice(5,6)

res34: Array[Int] = Array(6)

 

scala中的面向对象

面向对象三大特性  封装(方法)  继承(extends implements)  多态(继承)

接口 interface  abstract抽象类 class

scala  trait abstract object class

 

scala 中的对象object

object就是一个static的类,object是单例的,和javastatic修饰的东西一样,可以用来代替staticobject的对象不能new,所以全局只有初始化的时候声明的第一个实例

 

class abc{
  def main(args: Array[String]): Unit = {
    println(123)
  }
}

class修饰的main方法是不能运行的,因为不是static的,object修饰的类相当于在java中的static{}静态代码块

 

scalaobject对象在编译的时候会生成两个类,一个是普通的类,一个是带有$的虚类

 

普通的类中的修饰父是final形式的,所以这个object的类不能new,普通的object编译出来的类只有一个main方法,虚类中会存在很多的逻辑代码,虚类中在启动的时候static{new()}

在加载的时候首先new出来一个对象

 

object的使用

创建object与创建类是一样的,object中可以定义方法,可以定义属性

object test321{
  def main(args: Array[String]): Unit = {
    println(user)
    println(user)
    println(user)
    println(user)
  }

}
object user{
  println(123)
}

 

123

user$@140d5f0

user$@140d5f0

user$@140d5f0

user$@140d5f0

object使用的时候可以直接写object的名字,而且使用多次都是一个对象,但是这个对象只会被加载一次,object编译后的文件是一个static修饰的,所以我们在调用object的时候会执行其中的代码

 

伴生对象

在一个文件中名称相同的类和对象,那么这个类就是这个对象的伴生类,这个对象就是这个类的伴生对象,他们之间互为伴生

伴生对象可以访问伴生类中的私有属性和方法

class user{
  private val name = "赵四"
  private def getHello={
    println("hello")
  }
}

object student{
  def main(args: Array[String]): Unit = {
     val u = new user()
    val stu = new student
    stu.getHello
    stu.name
  }
}
class student{
  private def getHello={
    println("hello")
  }
  private val name = "刘能"
}

 

一般情况下我们都会创建对象的时候创建一个伴生的类

重点是在伴生对象中存在一个apply的方法

object testtt{
  def main(args: Array[String]): Unit = {
    val stu = new student
    val stu1 = student()
    println(student("志玲"))
  }
}
object student{
  def apply(): student = new student()
  def apply(name:String): String = "hi girl,u r "+name+"?"
  def main(args: Array[String]): Unit = {
     val u = new user()
    val stu = new student
    stu.getHello
    stu.name
  }
}

apply方法的特殊性是因为apply方法的名字,可以进行重载,调用apply方法object()

var stu:student = null
def apply(): student = {
  if(stu==null)
    stu=new student
  stu
}

其实可以通过私有构造器,然后重写伴生对象中的apply方法进行单例模式的创建

 

对象和实例的泛型

val stu: student = new student
val stu1: student = student()
val stu2: student.type = student

new出来的实例,泛型是class  对象的泛型是object.type

 

应用程序方法:

object testtt extends App{

  println(123)
  println(123)
  println(123)

  override def main(args: Array[String]): Unit = {
    println(234)
  }
  println(123)
  println(123)
  println(123)

}

一个object对象继承了App接口,那么这个接口中的main就可以将整个object中的代码全部都包含,如果在子类中重写了这个main方法,那么这个类中的其他代码就不会执行了

 

class类,new class()所产生东西叫做类的实例

类中可以声明方法和属性

public class Teacher

{

  private String name = "谢永强";

  private final int age = 40;

 

  public String name()

  {

    return this.name; }

  public void name_$eq(String x$1) { this.name = x$1; }

  public int age() { return this.age; }

  public void getHello() {

    Predef..MODULE$.println("hello");

  }

}

 

class Teacher{
  var name:String = _
  var age:Int = _
  val sex="男"
  def getHello(): Unit ={
    println("hello")
  }
}

object trrr{
  def main(args: Array[String]): Unit = {
    val tea = new Teacher
    tea.name = "刘德华"
    println(tea.age)
    println(tea.name)
    tea.getHello()
  }
}

var声明的属性一般都是带有set get方法的,val修饰的都是用final修饰的,只能存在get方法没有set方法
override def toString:String = s"name=${name}  age=${age}  sex= ${sex}"

s插值法,在字符串前面加上s,字符串中就可以使用${}进行取值

 

构造器:

scala中的构造器类似于java中的构造器

构造器主要分为两类,主构造器,辅助构造器

主构造器是在类后面的构造器

object trrr{
  def main(args: Array[String]): Unit = {
      val t = new tobacco()
      val t1 = new tobacco("红塔山","渣渣",7.5)
  }
}
class tobacco(logo:String,smell:String,price:Double){
}

主构造器在没有声明的时候就是一个空参构造器,如果构造器声明了,那么空参构造器就被覆盖掉了

object trrr{
  def main(args: Array[String]): Unit = {
      val t1 = new tobacco("红塔山","渣渣",7.5)
      println(t1.logo)
  }
}
class tobacco(var logo:String,smell:String,price:Double){
}

 

object trrr{
  def main(args: Array[String]): Unit = {
      val t1 = new tobacco("红塔山","渣渣",7.5)
      println(t1)
  }
}
class tobacco(var logo:String,smell:String,price:Double){
  override def toString: String = s"${logo}  ${smell}  ${price}"
}

 

在创建构造器的时候一定要指定val/var进行修饰,不然的话这个数据就是参数不是属性值,没有办法取值,作为参数传递到类中的值,可以在类内部使用

 

在一个类中构造器的参数和数据的名称不能重复

 

辅助构造器

class tobacco(var logo:String,smell:String,price:Double){
        def this(){
          //辅助构造器的第一行内容必须调用构造器
          this("芙蓉王","香",25)
        }
}

 

辅助构造器的第一行必须调用其他的构造器

 

 

posted @ 2019-09-16 14:31  lilixia  阅读(211)  评论(0编辑  收藏  举报