Scala03(包含如何写WordCount)

父类和子类

new 子类() 会先触发 new 父类()

子类 extends 父类

object ExtendsApp {
  def main(args: Array[String]): Unit = {
    val youngPerson = new YoungPerson("dashu","beijing",200.0f)
  }
}

class YoungPerson(name:String,city:String,money:Float)
  extends Person(name,city){             //定义一个子类YoungPerson,继承的是父类Person
  println("YoungPerson enter....")

  println("YoungPerson leave....")
}

class Person(val name:String,val city:String){   //父类
  println("person enter....")
  var age:Int =_

  //附属构造器 第一行必须要调用主构造器或者其他附属构造器
  def this(name:String,city:String,age:Int){
    this(name,city)
    this.age = age
  }
  println("person leave....")
}

运行结果:

person enter....
person leave....
YoungPerson enter....
YoungPerson leave....

Process finished with exit code 0

由此可知,new 子类() 会先触发 new 父类() ,所以从上面输出结果可以看出,先跑了父类的构造器,再跑了子类的构造器。

重写

Animal : eat
Dog eat
Cat eat
Pig eat
父类Animal定义了一个 吃
但子类 每个具体动物 吃的东西不一样,所以需要去重写父类的吃的方法。
重写:父类有一个方法,子类中也有一个一样的方法。
override 用来在子类中重写父类的方法或者属性。
调用的时候,默认走的是父类的方法,如果子类重写了,那么调用的就是子类的方法

object ExtendsApp {
  def main(args: Array[String]): Unit = {
    val youngperson = new YoungPerson("dashu","beijing",200.0f)

    //默认走的是父类的方法,如果子类重写了,那么调用的就是子类的方法
    println(youngperson.toString())
  }
}

class YoungPerson(name:String,city:String,money:Float)
  extends Person(name,city){
  println("YoungPerson enter....")

  override def toString() = "toString......" 

  println("YoungPerson leave....")
}

class Person(val name:String,val city:String){   //父类
  println("person enter....")
  var age:Int =_

  //附属构造器 第一行必须要调用主构造器或者其他附属构造器
  def this(name:String,city:String,age:Int){
    this(name,city)
    this.age = age
  }
  println("person leave....")
}

运行结果:

person enter....
person leave....
YoungPerson enter....
YoungPerson leave....
toString......

Process finished with exit code 0

在父类中并没有找到toString方法,Java最顶层是object,它里面就有toString方法。
如果把 override def toString() = “toString…” 这句话注释掉,那么在main方法中就会调用父类的方法,这里调用的是object的方法。注释掉这一行之后,运行结果如下:

person enter....
person leave....
YoungPerson enter....
YoungPerson leave....
YoungPerson@482f8f11

Process finished with exit code 0

object中的toString方法如下:

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

一般在框架中,都是定义一些接口,或者抽象类,并没有写具体的实现,具体的实现都是在子类中去实现。这样对于一个框架来说非常容易扩展。

抽象类

用关键字abstract修饰
①Class function 没有具体的实现
②抽象类不能直接new,而是通过子类(不能还是抽象的)来new
除了以上两个特点,抽象类和普通的类基本上没有什么区别,该做什么就做什么。
比如:

abstract class A{
  def speak()
  val name:String
}

抽象类定义和使用举例:

object AbstractApp {
  def main(args: Array[String]): Unit = {
    val a = new(B)
    a.speak()
  }
}

abstract class A{
  def speak()
  val name:String
}
class B extends A {     //B继承A,并具体实现A,包括属性和方法
  override def speak(): Unit = {
    println("B speak.....")
  }
  val name = "xiaoming"
}

trait(类似Java中的接口)

Scala中的trait:基本上可以等同于Java中的接口
trait和抽象类一样,也不能new的

如果D是trait,C来继承它,可以这样写:
class D extends C 在Scala中第一个继承用extends,后面再继承的话都用with

如果D是trait,A是类,C来继承它,可以这样写:
class D extends A with D
但是不能这样写:
class D extends D with A //类写在前面,trait写在后面

extends后面跟的一定是抽象类吗?不是,也可以是trait
但是with后面跟的都是trait

abstract class A{
  def speak()
  val name:String
}

class B extends A {
  override def speak(): Unit = {
    println("B speak.....")
  }
  val name = "xiaoming"
}

trait C{    //定义一个trait
  def c()
}

class D extends A with C {
  override def c(): Unit = {
    println("D jicheng C")
  }
  override def speak(): Unit = {
    println("D extends A")
  }
  override val name: String = _
}

Scala之高阶函数(重要)

首先了解一下map
map可以理解为映射,就像曾经学的y = f(x) 这样的函数一样,x作用于函数f,结果变成了y。
如果对一个集合内的每个元素都做一个相同的操作,就可以理解为映射。
f:Int => B 这个Int指的是集合里面元素的类型

现在来看一个例子:
现在有一个集合:l 里面有9个元素1~9

object FunctionApp {
  def main(args: Array[String]): Unit = {
  
    val l = List(1,2,3,4,5,6,7,8,9)     //这里暂时先把 l 理解为一个集合,里面有9个元素1~9
    
    println(  l.map((x:Int) => x*2)  )
    
  }
}

现在来看这行代码:l.map((x:Int) => x2)
map 是对 l 集合里面的每个元素进行操作
(x:Int) 这个就是集合里面的每个元素 x这个名字可以随便写,Int这个指的是集合里元素的类型 (x:Int) 这个就是函数的入参 (就和 y = f(x) 这样的函数一样x是入参)
然后把入参(x:Int) 就是每一个元素 把它变成 x
2这个元素 就是每个元素乘以2

其实我感觉 l.map((x:Int) => x2) 这个就是使用map这个函数,对立面的每个元素,进行操作,操作是x2,操作完成后,拿出来就是乘以2的结果了。

上面运行的结果:

List(2, 4, 6, 8, 10, 12, 14, 16, 18)

Process finished with exit code 0

然后再看这个代码:l.map((x:Int) => x2)
其实那个Int类型 Scala是可以自动推导出来的,
所以可以这样写:l.map((x) => x
2)
然后x的括号也可以去掉,所以可以这样写:
l.map(x => x*2) //可以很明显的看出来,是把里面的元素每个都乘以2
然后 还可以这样写:*l.map(_2)
这个下划线表示 l 集合里面的每一个元素
所以就可以这样了:

object FunctionApp {
  def main(args: Array[String]): Unit = {
    val l = List(1,2,3,4,5,6,7,8,9)
    println(  l.map(_*2)  )
  }
}

现在如果要求筛选出集合里面大于10的元素,如何筛选?
有个函数: filter(p: A => Boolean) 进来一个A,出来一个布尔型
比如进来一个 100,出来一个 100>0 ,100>0 的结果是true,那么结果就是true

源码里面对这个filter函数的描述是:Selects all elements of this $coll which satisfy a predicate 选择集合里面满足条件的元素

所以就可以这样筛选了:

l.map(_*2).filter(_ > 10)

这个其实就是链式编程
先用map对l集合里面的没个元素乘以2,然后再用filter对前面的结果进行筛选,大于10的。

object FunctionApp {
  def main(args: Array[String]): Unit = {
    val l = List(1,2,3,4,5,6,7,8,9)
    println(  l.map(_*2)  )
    println(  l.map(_*2).filter(_ > 10)  )
  }
}

输出的结果为:

List(2, 4, 6, 8, 10, 12, 14, 16, 18)
List(12, 14, 16, 18)

Process finished with exit code 0

现在如果再进行筛选,取集合里前面2个元素呢?
有个 take(n: Int) 函数,就是取集合里面前n个元素。
所以:

object FunctionApp {
  def main(args: Array[String]): Unit = {
    val l = List(1,2,3,4,5,6,7,8,9)
    //println(  l.map((x:Int) => x*2)  )
    println(  l.map(_*2)  )
    println(  l.map(_*2).filter(_ > 10)  )
    println(  l.map(_*2).filter(_ > 10).take(2)  )    //take
  }
}

运行结果:

List(2, 4, 6, 8, 10, 12, 14, 16, 18)
List(12, 14, 16, 18)
List(12, 14)

Process finished with exit code 0

那现在如果求两两相邻的数字加起来,求和,如何写?
List(1,2,3,4,5,6,7,8,9)
1+2+3+4+5+6+7+8+9=?
实现:
1+2=3
3+3=6
6+4=10
10+5=15

Scala中,两两操作,比如两两相加,可以借助于reduce这个函数。
reduce(op: (A1, A1) => A1) 进去两个值,进行一番操作后,出来一个值

相加的话就可以这样写了,
l.reduce( (x:Int,y:Int) => x+y) 进去x y 出来 x+y
在这基础上,可以简写:
l.reduce(_ + _)

再举例:
这个函数 l.reduceLeft((x:Int,y:Int) => x-y)
进行扩展之后可以这样:

l.reduceLeft((x:Int,y:Int) => {
println(x + “,” + y)
x-y
})

object FunctionApp {
  def main(args: Array[String]): Unit = {
    val l = List(1,2,3,4,5,6,7,8,9)

    //l.reduceLeft((x:Int,y:Int) => x-y)
    l.reduceLeft((x:Int,y:Int) => {
      println(x + "," + y)
      x-y
    })
    
  }
}

输出结果:

1,2
-1,3
-4,4
-8,5
-13,6
-19,7
-26,8
-34,9

Process finished with exit code 0

再看一个函数:

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

使用: l.fold(10)((x:Int,y:Int) => x-y)
有两个括号 两个参数

object FunctionApp {
  def main(args: Array[String]): Unit = {
    val l = List(1,2,3,4,5,6,7,8,9)

    l.fold(10)((x:Int,y:Int) => x-y)
    l.fold(10)((x:Int,y:Int) => {
            println(x + "," + y)
            x+y
          })
  }
}

运行结果:

10,1
11,2
13,3
16,4
20,5
25,6
31,7
38,8
46,9

Process finished with exit code 0

从上面可以看出,给了它一个初始值10,从10开始相加的。

另外对于集合 val l = List(1,2,3,4,5,6,7,8,9)
可以直接这样:

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

scala> l.max
res0: Int = 9

scala> l.min
res1: Int = 1

scala> l.sum
res2: Int = 45

scala> l.count(_ >3)
res3: Int = 6

scala>

高阶函数2

spark中Scala写的WordCount源码:

https://github.com/apache/spark/blob/master/examples/src/main/scala/org/apache/spark/examples/streaming/HdfsWordCount.scala

这个复杂一些:
List里面套 List:
val a = List(List(1,2),List(3,4),List(5,6),List(7,8))
再调用a.flatten 这个,效果如下:
在这里插入图片描述
然后
在这里插入图片描述
下面看这个函数:flatMap
flatMap ==等价于 flatten + map

val a = List(List(1,2),List(3,4),List(5,6),List(7,8))
a.flatMap(.map(*2))
_下划线 表示里面每个元素,每个元素都是一个List,先压扁,然后每个元素乘以2
效果如下:
在这里插入图片描述

WordCount

现在假如有个List,这个List叫做line,List里面还是List

#line=
hello  hello  world
count china
hello  count
love

val words = lines.flatMap(_.split(" "))
表示先把它压扁,压扁之后,按照空格进行分割,
这个操作之后变成这样:

#words =
hello hello world count china hello count love

words.map(x => (x, 1))
这个是对里面元素,每个元素赋上一个1,
变成了这样:

(hello,1) (hello,1) (world,1) (count,1) (china,1) (hello,1) (count,1) (love,1) 

备注:做reduce的时候,入参是(key,<1,1,1…>),
按照上面就是reduce(hello,<1,1,1>) 输出的结果是 (hello,3)

reduceByKey(_ + _) 这个是根据相同的key进行相加求和

所以:
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)
输出结果就是:

(hello,4)  (world,1) (count,2) (china,1)(love,1) 

以上只是简单分析一下,后面还要详细进行分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值