目录
简介
在Scala中,面向对象的实现是纯的:每个值都是对象,每个操作都是方法调用。Scala也是功能完整的函数式编程语言。以两大核心理念为指导。第一个理念是函数式一等的值。可以将函数作为参数传递给其他函数,作为返回值返回它们。第二个核心理念是程序中的操作应该将输入值映射成输出值,而不是当场修改数据。即,方法只能通过接收入参和返回结果这两种方式与外部环境通信。
同时拥有兼容性,精简性,高级性,静态类型
一.首先创建一个Weathers类
定义类的属性,对多个名称定义属性
class Weathers(var date: String, //日期
var location: String, //气象站名称
var minTemp: String, //最低温度
var maxTemp: String, //最高温度
var rainfall: String, //当天记录的降雨量(毫米)
var windGustDir: String, //24小时至午夜期间最强阵风的方向
var windGustSpeed: String, //到午夜24小时内最强阵风的速度(km \/ h)
var windDir9am: String, //上午9点的风向
var windDir3pm: String, //下午3点的风向
var windSpeed9am: String, //下午9点前十分钟的平均风速
var windSpeed3pm: String, //下午3点前十分钟的平均风速
var humidity9am: String, //上午9点的湿度(百分比)
var humidity3pm: String, //下午3点的湿度(百分比)
var pressure9am: String, //上午9点时大气压(hpa)降低至平均海平面
var pressure3pm: String, //下午3点时大气压(hpa)降低至平均海平面
var cloud3pm: String, //下午3点,云层遮盖了天空的比例。 以“ oktas”为单位,该单位是高度的单位.
var temp9am: String, //上午9点的温度(摄氏度)
var temp3pm: String, //下午3点的温度(摄氏度)
var rainToday: String, //如果24小时至上午9点的降水量(mm)超过1mm,则为YES,否则为NO
var rainTomorrow: String //第二天的雨量,以毫米为单位。一种衡量“风险”的方法。第二天降雨则YES,否则为NO
)extends Serializable{
}
二.使用window算子
该算子的作用是将源DStream转成窗口DStream,从语法层面看不出它们有什么不同,但是包含的数据是不一样的,简单理解,转换前表示一个个批次的数据,转换后,表示一个个窗口的数据
val sparkConf = new SparkConf().setAppName(LocationYearSum.getClass.getName).setMaster("local[2]")
//批次间隔
val sc = new StreamingContext(sparkConf, Duration(1000*1))
sc.checkpoint("yearSum")
val dStream = sc.socketTextStream("192.168.128.53", 9999)
//窗口长度5秒,滑动间隔10秒
val window = dStream.window(Duration(1000*5),Duration(1000*10))
三.读取文件内容信息
Weathers是车辆信息json文件需要自己导入
map(it => {
var weather: Weathers = new Gson().fromJson(it, classOf[Weathers])
var year: String = conversion(weather.date)
var locationYear = weather.location + "_" + year
(locationYear, 1)
})
四.使用updateStateByKey函数
updateStateByKey操作允许您在使用新的信息持续更新时保持任意状态
updateStateByKey((values: Seq[Int], state: Option[Int]) => {
val sum = values.sum + state.getOrElse(0) //上一个窗口的状态不存在(即为None)则默认使用0作为值
Some(sum) //将计算得到的新状态值封装起来
五.foreachRDD输出操作符
foreachRDD 是一个输出操作符,它返回的不是RDD里的一行数据, 而是输出DStream后面的RDD, 在一个时间间隔里, 只返回一个RDD的“微批次”, 为了访问这个“微批次”RDD里的数据
foreachRDD(it => {
it.foreachPartition(io => {
Class.forName("com.mysql.cj.jdbc.Driver")
val url = "jdbc:mysql://192.168.65.3:3306/hadoop?useSSL=false&characterEncoding=utf-8"
val conn = DriverManager.getConnection(url, "root", "Aa123-456")
var prepare = conn.prepareStatement("insert into weather_location(location,date,count)values(?,?,?)")
while (io.hasNext) {
var data = io.next()
prepare.setString(1, data._1.split("_")(0))
prepare.setString(2, data._1.split("_")(1))
prepare.setInt(3, data._2)
prepare.execute()
}
conn.close()
prepare.close()
})
})
附完整代码
object LocationYearSum {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setAppName(LocationYearSum.getClass.getName).setMaster("local[2]")
//批次间隔
val sc = new StreamingContext(sparkConf, Duration(1000*1))
sc.checkpoint("yearSum")
val dStream = sc.socketTextStream("192.168.128.53", 9999)
//窗口长度5秒,滑动间隔10秒
val window = dStream.window(Duration(1000*5),Duration(1000*10))
window.map(it => {
var weather: Weathers = new Gson().fromJson(it, classOf[Weathers])
var year: String = conversion(weather.date)
var locationYear = weather.location + "_" + year
(locationYear, 1)
}).updateStateByKey((values: Seq[Int], state: Option[Int]) => {
val sum = values.sum + state.getOrElse(0) //上一个窗口的状态不存在(即为None)则默认使用0作为值
Some(sum) //将计算得到的新状态值封装起来
}).foreachRDD(it => {
it.foreachPartition(io => {
Class.forName("com.mysql.cj.jdbc.Driver")
val url = "jdbc:mysql://192.168.65.3:3306/hadoop?useSSL=false&characterEncoding=utf-8"
val conn = DriverManager.getConnection(url, "root", "Aa123-456")
var prepare = conn.prepareStatement("insert into weather_location(location,date,count)values(?,?,?)")
while (io.hasNext) {
var data = io.next()
prepare.setString(1, data._1.split("_")(0))
prepare.setString(2, data._1.split("_")(1))
prepare.setInt(3, data._2)
prepare.execute()
}
conn.close()
prepare.close()
})
})
sc.start()
sc.awaitTermination()
sc.stop()
}
def conversion(date: String): String = {
val dateSplit = date.split("/")
dateSplit(0)
}
}
总结
总的来说,Scala是一门功能强大而又灵活多变的编程语言,适合构建高性能、可扩展和维护的应用程序。它的学习曲线可能会略高一些,但一旦掌握,将能带来更好的编程体验和效果。
1.简洁优雅
Scala采用简洁的语法和强大的类型推断,可以用更少的代码实现相同的功能,提高了开发效率。
2.函数式编程
Scala支持函数式编程,函数是一等公民,可以将函数作为参数传递和返回值返回,让代码更加灵活和模块化。
3.面向对象编程
Scala完全兼容Java的面向对象编程特性,可以无缝地与Java代码进行交互,方便扩展和重用现有的Java库。
4.强大的类型系统
Scala的类型系统非常丰富和灵活,支持高阶类型、类型推断、类型参数化等特性,使得代码更加健壮和可维护。
5.并发编程
Scala内置了用于并发编程的库,如Actors和Futures,可以方便地处理并发任务,提高程序的性能和响应能力。
6.表达力强
Scala提供了丰富的语法和类型特性,可以用多种方式解决问题,让代码更具表达力和可读性。