scala04课件
作业题
object HomeWorke232424r {
|
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是单例的,和java中static修饰的东西一样,可以用来代替static,object的对象不能new,所以全局只有初始化的时候声明的第一个实例
class abc{ |
用class修饰的main方法是不能运行的,因为不是static的,object修饰的类相当于在java中的static{}静态代码块
scala的object对象在编译的时候会生成两个类,一个是普通的类,一个是带有$的虚类
普通的类中的修饰父是final形式的,所以这个object的类不能new,普通的object编译出来的类只有一个main方法,虚类中会存在很多的逻辑代码,虚类中在启动的时候static{new()}
在加载的时候首先new出来一个对象
object的使用
创建object与创建类是一样的,object中可以定义方法,可以定义属性
object test321{
123 user$@140d5f0 user$@140d5f0 user$@140d5f0 user$@140d5f0 |
object使用的时候可以直接写object的名字,而且使用多次都是一个对象,但是这个对象只会被加载一次,object编译后的文件是一个static修饰的,所以我们在调用object的时候会执行其中的代码
伴生对象
在一个文件中名称相同的类和对象,那么这个类就是这个对象的伴生类,这个对象就是这个类的伴生对象,他们之间互为伴生
伴生对象可以访问伴生类中的私有属性和方法
class user{
|
一般情况下我们都会创建对象的时候创建一个伴生的类
重点是在伴生对象中存在一个apply的方法
object testtt{ |
apply方法的特殊性是因为apply方法的名字,可以进行重载,调用apply方法object()
var stu:student = null |
其实可以通过私有构造器,然后重写伴生对象中的apply方法进行单例模式的创建
对象和实例的泛型
val stu: student = new student |
类new出来的实例,泛型是class 对象的泛型是object.type
应用程序方法:
object testtt extends App{ |
一个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声明的属性一般都是带有set get方法的,val修饰的都是用final修饰的,只能存在get方法没有set方法
override def toString:String = s"name=${name} age=${age} sex= ${sex}"
s插值法,在字符串前面加上s,字符串中就可以使用${}进行取值
构造器:
scala中的构造器类似于java中的构造器
构造器主要分为两类,主构造器,辅助构造器
主构造器是在类后面的构造器
object trrr{ |
主构造器在没有声明的时候就是一个空参构造器,如果构造器声明了,那么空参构造器就被覆盖掉了
object trrr{
object trrr{
|
在创建构造器的时候一定要指定val/var进行修饰,不然的话这个数据就是参数不是属性值,没有办法取值,作为参数传递到类中的值,可以在类内部使用
在一个类中构造器的参数和数据的名称不能重复
辅助构造器
class tobacco(var logo:String,smell:String,price:Double){ |
辅助构造器的第一行必须调用其他的构造器