开发者学堂课程【大数据 Spark2020版(知识精讲与实战演练)第四阶段:数据清洗_异常处理_Either】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/691/detail/12113
数据清洗_异常处理_Either
Either
数据转换之间容易出现异常
如,有一个变量
val d
d.toString
val s
s.toDouble
在 s 上 toDouble 容易出现问题
异常处理
在进行类型转换的时候,是一个非常容易错误的点,需要进行单独的处理。
Step 1:思路
在 DataFrame 中调用 map,进行数据转换,DataFrame 中是 row,map 转换成 trip 类型,map 直接调用 parse 方法,parse 调用 parseLocation 和 parseTime,parseLocation 和 parseTime 执行具体数据类型转换,在 parseLocation 和 parseTime 特别容易出现错误,调用 parseLocation 和 parseTime,先去接触异常,在 parse 方法中进行异常处理。
异常处理有两种方法
parse 方法中未出现异常,直接返回正确
DataFtame.map 中调用 parse 方法,parse 方法中未出现异常,返回结果;parse 出现异常,返回异常信息、返回参数。
Parse 方法的设计:
(1)应该捕获异常
(2)出现异常返回异常信息与当前这次调用的参数
(3)没有异常返回结果
DataFrame 的处理算子中,可以针对异常进行处理和怕判断
parse 中调用了以下两个方法,所以报错会进入 parse
真正类型转换出错一般发生在转换时
对于 parse 方法来说,如果处理了异常,则会返回两种情况
(1)正确返回 Left
(2)异常返回 Right
parse 方法应该做的事情应该有两件
·捕获异常
异常一定是要捕获的,无论是否要抛给 DataFrame ,都要先捕获一下,获知异常信息捕获要使用 try .. catch ... 代码块
返回结果
返回结果应该分为两部分来进行说明
正确,正确则返回数据
错误,则应该返回两类信息,一告知外面哪个数据出了错,二告知错误是什么。
对于这种情况,可以使用 Scala 中提供的一个类似于其它语言中多返回值的.Either 分为两个情况,一个是 Left,一个是 Right ,左右两个结果所代表的意思可有由用户来指定。
打开 idea
创建新的类
设计一个方法,是具体执行的方法
process 接收一个 b,返回结果是另外一个 Double,不能传入0,0不能作为被除数,对错误进行包装
接收两个参数,f,接收一个 Double 返回一个 Double,b,转成一个 Double,b是传入 process 内容,Either 有两种情况,第一个是正确,返回 Double,第二种是异常,Double 是接收的参数,将当前调用函数的参数明确在什么情况下出现异常,明确是什么异常,Either 代表二选一,Double 代表左的情况,代表正常, Double,Exception 代表右的情况,代表异常
Try 一下,在 try 中调用函数,让外面将函数和参数传入,在 safe 中 try 调用,获取 result
Either 相当于 Left 或 Right,代表左情况或右情况,返回正确是左情况,接收 result,返回异常是右情况,接收两个参数,b 和 e,left 对应 Double,Right 对应 Double,Exception,Either 是 left 和 right 代表的两种情况的表示
Option 是 some、none,some 有值,none 没有值
def safe(f: Double => Double,b: Double):Either[Double,(Double,Exception)] = {
try {
val result = f(b)
Left(result)
}catch {
case e: Exception => Right(b,e)
}
方法中返回 option 不行,可以返回 none,但是将参数与 exception 错误带出,让外部明确错误,option 不可以,只能是 either
Left 代表正常行为,Right 代表异常行为是可以的,都是一样的
调用 safe,将 process 函数传入,将需要的值传入,就能获取 result。
//process(0.0)
val result = safe(process,0)
result match {
case Left(r) => println(r)
case Right((b,e)) => printLn(b,e)
}
}
运行
将代码放入 main 方法中
package cn.itcast.taxi
object EitherTest {
def main(args: Array [string]): unit = {
/**
*相当于 Parse方法
*/
def process(b: Double) : Double = {
val a = 10.0
a / b
}
// Either => Left or Right
// option => some None
def safe(f: Double => Double,b: Double):Either[Double,(Double,Exception)] = {
try {
val result = f(b)
Left(result)
}catch {
case e: Exception => Right(b,e)
}
}
//process(0.0)
val result = safe(process,0)
result match {
case Left(r) => println(r)
case Right((b,e)) => printLn(b,e)
}
}
对应 Infinity,任何数字除以0返回是 Infinity,无限,没有出现异常。
在 parse 调用时,有可能出现异常,不要直接调用 process,要通过 safe 的方法包装,真正调用 safe,把 process 方法传入,将函数和参数传入,process 在 safe 方法内调用,把0传入 process 方法中,safe 中调用是安全的,所有的异常都会捕获掉。
Safe 有两种情况返回值,一种情况是没有报错,left将值直接带出,另一种情况是报错,返回当前参数以及异常信息。
通过 safe 调用获取结果,获取结果通过 result.right.get 或 result.left.get,result 是 left,通过 right 获取值会报错,可以通过 isleft 判断是否是 left。

