一、flatmap与map的区别
1. map会将每一条输入映射为一个新对象。{苹果,梨子}.map(去皮) = {去皮苹果,去皮梨子} 其中: “去皮”函数的类型为:A => B
不能把一行 映射为多行。
2.flatMap包含两个操作:会将每一个输入对象输入映射为一个新集合,然后把这些新集合连成一个大集合。 {苹果,梨子}.flatMap(切碎) = {苹果碎片1,苹果碎片2,梨子碎片1,梨子碎片2} 其中: “切碎”函数的类型为: A => List<B>
可以将1行切为多行。
例子:
import java.sql.Timestamp
import java.text.SimpleDateFormat
import java.util
import java.util.{Collections, Date}
import com.gree.util.DateUtil.DateFormat
import com.gree.util.DmSpark
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.{DataFrame, SQLContext, SaveMode}
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
import scala.collection.mutable.ArrayBuffer
/**
*
* ClassName: 一条记录变多条记录
* Description:输入一条记录只包括开始时间和结束时间,然后按小时切断,变为N条记录
* author yuwei
* date 2018年9月29日
*
*/
object DayToperMin {
private val sc = DmSpark.getSC()
private val sqlHiveContext = DmSpark.getSqlHiveContext()
val sqlContext = new SQLContext(sc)
import sqlHiveContext.implicits._
def main(args: Array[String]): Unit = {
// Tuple类型
val ab = new ArrayBuffer[(Long, Timestamp, Timestamp, Timestamp)]()
val data4 = sqlHiveContext.createDataFrame(Seq((Timestamp.valueOf("2018-08-08 00:37:36.0"), Timestamp.valueOf("2018-08-09 01:05:59.0"))
,(Timestamp.valueOf("2018-09-08 00:37:36.0"), Timestamp.valueOf("2018-09-09 01:05:59.0"))))
.toDF("recordtime", "leadrecordtime")
.withColumn("dif", 'leadrecordtime.cast("long") - 'recordtime.cast("long"))
// 用flatMap不用map的原因:map 输入输出是1对1,flatmap输入1 输出1个list
.rdd.flatMap(x => {
// 按分钟切
// val s=Timestamp.valueOf(x.get(0).toString.substring(0,17)+"00")
// val e=Timestamp.valueOf(x.get(1).toString.substring(0,17)+"00")
// 按小时切
val s = Timestamp.valueOf(x.get(0).toString.substring(0, 14) + "00:00")
val e = Timestamp.valueOf(x.get(1).toString.substring(0, 14) + "00:00")
val difNum = DateFormat(e) - DateFormat(s)
println(s, e, difNum)
//用java 的ArrayList需要import scala.collection.JavaConversions._ 才能在后续scala中使用
// scala中只有Array(定长),ArrayBuffer(变长),这里是变长,用ArrayBuffer
// val arr=new util.ArrayList[String]()
val first = Timestamp.valueOf(x.get(0).toString)
ab.+=((x.get(2).toString.toLong, x.getTimestamp(0), first, x.getTimestamp(1)))
val end = Timestamp.valueOf(x.get(1).toString)
ab.+=((x.get(2).toString.toLong, x.getTimestamp(0), end, x.getTimestamp(1)))
for (i: Long <- 3600L to difNum by (3600L)) {
val time1 = getAddTime(s, i)
// arr.add(x.get(2).toString.toLong + "," + x.getTimestamp(0) + "," + time1 + "," + x.getTimestamp(1))
ab.+= ((x.get(2).toString.toLong, x.getTimestamp(0), time1, x.getTimestamp(1)))
}
// import scala.collection.JavaConversions._
// arr
ab
}) /*.map(x => {
val arr = x.split(",")
(arr(0), arr(1), arr(2), arr(3))
})*/
.toDF("difNum","recordtime","perHour","leadRecordtime")
.orderBy('perHour)
.show(1000, false)
}
//求某个时间的向前或向后x秒的时间
def getAddTime(start_Time: Timestamp, interval: Long): Timestamp = {
var sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
var timeFormt = "yyyy-MM-dd HH:mm:ss"
var time: Long = DateFormat(start_Time)
val addtime: Long = time + interval
val addtime1: String = sdf.format(addtime * 1000)
val finaltime = Timestamp.valueOf(addtime1)
finaltime
}
def DateFormat(time: Timestamp): Long = {
val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") //定义格式,不显示毫秒
val dt: Date = sdf.parse(time.toString)
dt.getTime() / 1000
}
}
(2018-08-08 00:00:00.0,2018-08-09 01:00:00.0,90000)
(2018-09-08 00:00:00.0,2018-09-09 01:00:00.0,90000)
+------+---------------------+---------------------+---------------------+
|difNum|recordtime |perHour |leadRecordtime |
+------+---------------------+---------------------+---------------------+
|88103 |2018-08-08 00:37:36.0|2018-08-08 00:37:36.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 01:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 02:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 03:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 04:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 05:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 06:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 07:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 08:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 09:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 10:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 11:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 12:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 13:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 14:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 15:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 16:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 17:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 18:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 19:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 20:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 21:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 22:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-08 23:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-09 00:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-09 01:00:00.0|2018-08-09 01:05:59.0|
|88103 |2018-08-08 00:37:36.0|2018-08-09 01:05:59.0|2018-08-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 00:37:36.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 01:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 02:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 03:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 04:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 05:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 06:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 07:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 08:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 09:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 10:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 11:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 12:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 13:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 14:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 15:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 16:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 17:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 18:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 19:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 20:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 21:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 22:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-08 23:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-09 00:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-09 01:00:00.0|2018-09-09 01:05:59.0|
|88103 |2018-09-08 00:37:36.0|2018-09-09 01:05:59.0|2018-09-09 01:05:59.0|
+------+---------------------+---------------------+---------------------+
从spark的map到线程安全 mapPartition
http://jszhujun2010.farbox.com/post/spark/cong-sparkde-mapdao-xian-cheng-an-quan
二、scala中List、Array、ListBuffer、ArrayList、Set、元组区别
注意:scala中没有arrayList,使用java的arrayList时,需要import scala.collection.JavaConversions._
1.List列表:不可变
LIst支持在头部快速添加和移除条目,但是不提供快速按下标访问的功能,这个功能需要线性遍历列。
快速的头部添加和移除意味着模式匹配很顺畅
List列表跟数组非常像,2者都是同构的,同一个列表的所有元素必须是相同类型。
但是有2个重要区别
1,List是不可变的,元素不能通过赋值改变。
2.列表的结构是递归的(即链表,linkedList),而数组是平等的。
使用toList、toArray相互转换:
scala> Array(1,2,3).toList
res14: List[Int] = List(1, 2, 3)
scala> List(1,2,3).toArray
res15: Array[Int] = Array(1, 2, 3)
2.Array数组:可变
提供下标高效访问(获取或更新)指定位置的元素值
3.列表缓冲LIstBuffer:可变
List提供头部快速访问,对尾部访问则没那么高效。List追加元素,通常考虑反过来,追加元素,再调用reverset
另一个可选方案,使用ListBuffer,提供了常量时间的往后追加和往前追加的操作,最后调用toList获取List。
4.数组缓冲ArrayBuffer:可变
跟Array很像,除了可以额外地从序列头部或尾部添加或移除元素。
所有的Array操作在ArrayBuffer都可用。不过由于实现的包装,会稍慢一些。
新的添加和移除操作平均而言是常量时间,不过偶尔会需要线性的时间,这是因为其实现需要不时地分配新的数组来保存缓存的内容。
5.集Set,提供了可变和不可变
每个元素对象最多出现一次
6.元组
不同于数组或列表可以持有不同类型的对象(数组和列表也可以存,不过泛型参数就变为Any了)
7.Map,提供了可变和不可变
这里顺便说下传名参数:
val cache = scala.collection.mutable.Map(1-> "a",2-> "b",3->"c")
定义一个函数:
scala> def f(x: String) = {
| println("taking my time"); Thread.sleep(100)
| x.reverse}
//defgetOrElseUpdate(key: A, op: ⇒ B): B,第二个参数是个传名参数,所以如果k存在,不会执行。
scala> cache.getOrElseUpdate(10,f("abc"))
taking my time
res33: String = cba
---------------------
作者:疯狂的赣江
来源:CSDN
原文:https://blog.csdn.net/mar_ljh/article/details/81910286
版权声明:本文为博主原创文章,转载请附上博文链接!