求连续登陆的用户日期

guid01,2018-02-28
guid01,2018-03-01
guid01,2018-03-02
guid01,2018-03-04
guid01,2018-03-05
guid01,2018-03-06
guid01,2018-03-07
guid02,2018-03-01
guid02,2018-03-02
guid02,2018-03-03
guid02,2018-03-06
 //第一个参数就传true或false因为以后有可能在本地执行,有可能提交到集群里面
    val islocal = args(0).toBoolean
    //这个主要作用是获取对象
    val conf = new SparkConf().setAppName(this.getClass.getCanonicalName)

    //通过if判断是local模式运行吗
    if(islocal){  //判断是否是本地运行模式,如果是则走本地运行
      conf.setMaster("local[*]")
    }
    //以后指定从哪里读取数据创建RDD
    val sc: SparkContext = new SparkContext(conf)

    //以后指定从哪里读取数据创建RDD,以后通过参数把他传进来
    val lines: RDD[String] = sc.textFile(args(1))

    //对数据进行整理
    val uidAndDate: RDD[(String, String)] = lines.map(line => {
      val fields = line.split(",") //先用逗号切分
      val uid = fields(0)  //把Uid存到 0 号区
      val date = fields(1)  //存到1号区
      (uid, date)  //然后把uid和date放到一起
    })
    //根据uid进行分组,将同一个用户的登录数据搞到同一个组内
    //注意对于k-v类型调用groupByKey最好
    val grouped: RDD[(String, Iterable[String])] = uidAndDate.groupByKey()

    //在组内的value值进行排序
    val uidAndDateDiff: RDD[(String, (String, String))] = grouped.flatMapValues(it => { //把value压平,再把key合在一起
      //将迭代器中的数据toList/toSet ,由于可能会出现某个用户每一天会多次登录,所以必须要先对日期去重,然后再转成列表
      //在对列表进行排序
      val sorted: List[String] = it.toSet.toList.sorted
      //定义一个日期类工具,表示可以对日期进行操作
      val calendar = Calendar.getInstance()
      //创建个日期形式
      val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
      var index = 0
      sorted.map(dateStr => {
        val date: Date = sdf.parse(dateStr) //转成sdf定义的日期格式,本来是日期格式然后转换成date格式
        calendar.setTime(date)  //启动修改时间的机制
        calendar.add(Calendar.DATE, -index)
        index += 1
        //dateStr是指原来的时间,第二个参数是把当前时间拿出来
        (dateStr, sdf.format(calendar.getTime))
      })
    })

   /* val res: Array[(String, (String, String))] = uidAndDateDiff.collect()
    println(res.toBuffer)
    sc.stop()*/
    //(guid01,(2018-03-04,2018-03-01))

    val result1: RDD[((String, String), Iterable[String])] = uidAndDateDiff.map(t => {
      //参数1 key值,也就是uid t._2._2 表示被减去之后的日期,
      ((t._1, t._2._2), t._2._1) //表示登录的日期
      //按照key进行分组,查看组内有几条数据
    }).groupByKey()
    //对value进行操作
    val result2: RDD[(String, Int, String, String)] = result1.mapValues(it => {
      val list: List[String] = it.toList
      val times = list.size
      //怎样才能拿出一个起始时间,和一个结束时间呢
      val beginTime: String = list.head
      val endTime: String = list.last
      (times, beginTime, endTime)

    }).map(t => {
      //用户ID,连续多少天,起始时间,结束时间,
      (t._1._1, t._2._1, t._2._2, t._2._3)
    })
    println(result2.collect().toBuffer)
    sc.stop()

 

    //第一个参数传入true或false,因为后面肯能会在本地或者集群中运行
    val isLocal: Boolean = args(0).toBoolean
    //这个主要作用是获取对象
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getCanonicalName)

    //通过if判断是否在本地运行,一般在做测试的时候,是在本地运行
    if(isLocal){
      conf.setMaster("local[*]")
    }

    //指定以后在哪里读取数据
    val sc = new SparkContext(conf)

    //当读取数据完后,以后通过参数把他传进来,这样是一行一行的读取
    val lines: RDD[String] = sc.textFile(args(1))

    //对数据进行整理
    val uidAndDate: RDD[(String, String)] = lines.map(line => {
      //切割数据
      val fields: Array[String] = line.split(",")
      //把数据存储到相应的数组里面
      val uid: String = fields(0) //存放uid
      val date: String = fields(1) //存放日期,注意这些都是string类型
      (uid, date)
    })
    //现在对uid和日期进行处理并存放在数组里面,现在如何对日期进行处理
    //先对他按照key进行分组聚合
    val grouped: RDD[(String, Iterable[String])] = uidAndDate.groupByKey()
    /*val result: mutable.Buffer[(String, Iterable[String])] = grouped.collect().toBuffer
    println(result)
    //(guid01,CompactBuffer(2018-02-28, 2018-03-01, 2018-03-02, 2018-03-04, 2018-03-05, 2018-03-06, 2018-03-07))*/

    val uidAndDateDiff: RDD[(String, (String, String))] = grouped.flatMapValues(t => { //让每一个value值与key合在一起
      //先对value里面的元素进行操作
      val sorted: List[String] = t.toSet.toList.sorted
      //定义一个日期工具类,后面可对日期进行操作
      val calendar: Calendar = Calendar.getInstance()
      //创建一个日期格式,把日期进行格式化
      val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
      var index = 0
      sorted.map(dateStr => {
        //把string类型格式的日期转成格式化类型
        val date = sdf.parse(dateStr)
        //把设置好的日期放到Calendar里面
        calendar.setTime(date)
        calendar.add(Calendar.DATE, -index)
        index += 1
        (dateStr, sdf.format(calendar.getTime)) //获取当前时间
      })
    })
    //在完成分组聚合之后再对value  map一下  (guid01,2018-02-28), (guid01,2018-03-01),
   // val result1: Array[(String, (String, String))] = uidAndDateDiff.collect()
   // println(result1.toBuffer)
    //guid01,(2018-02-28,2018-02-28))


    val result1: RDD[((String, String), String)] = uidAndDateDiff.map(t => {
      ((t._1, t._2._2), t._2._1) //显示uid,被减去之后的日期,和初始登录日期

    })
    val res: RDD[((String, String), Iterable[String])] = result1.groupByKey()
    //val tuples: Array[((String, String), Iterable[String])] = res.collect()
   // println(tuples.toBuffer)
  //((guid02,2018-03-01),CompactBuffer(2018-03-01, 2018-03-02, 2018-03-03))

    //继续操作
    val res2: RDD[((String, String), (Int, String, String))] = res.mapValues(t => { //注意着仅仅只是对value进行处理
      //先把整个元组转成列表的形式
      val list: List[String] = t.toList
      val times: Int = list.size
      val beginTime: String = list.head
      val lastTime: String = list.last
      (times, beginTime, lastTime)
    })
    val res3: RDD[(String, Int, String, String)] = res2.map(t => {
      (t._1._1, t._2._1, t._2._2, t._2._3)
    })
    println(res3.collect().toBuffer)
    sc.stop()
    //(guid02,3,2018-03-01,2018-03-03)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值