Spark 如何过滤重复的对象

数据如下所示:

hello    world
hello    spark
hello    hive
hello    world
hello    spark
hello    hive

最终需要的只是

hello    world
hello    spark
hello    hive

这三个,重复的丢掉。有两种实现方法。

第一:在程序将文本加载进来形成line Rdd的时候调用distinct直接过滤掉,如:

lineRdd.distinct()

但是上面这种情况仅限于测试,因为实际数据不可能只有两列的数据,最常见的就是要根据其中几列的值来判断是否相同,如果相同则去重。

第二:将数据封装成对象的时候直接过滤掉,这个就要使用reduceByKey()了,因为distinct只能过滤数字和字符串的值,而且distinct的源码也是这样实现的。可以先看一下源码:

/**
 * Return a new RDD containing the distinct elements in this RDD.
 */
def distinct(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T] = withScope {
  map(x => (x, null)).reduceByKey((x, y) => x, numPartitions).map(_._1)
}

/**
 * Return a new RDD containing the distinct elements in this RDD.
 */
def distinct(): RDD[T] = withScope {
  distinct(partitions.length)
}

具体的源码解析可以参照这篇文章:http://blog.csdn.net/u014393917/article/details/50602431

下面是我参考源码的实现方式对一个对象进行的过滤:

代码实现:

 def main (args: Array[String]) {

    val conf = new SparkConf().setMaster("local[*]").setAppName("MapTest")
    conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
    // 注册要序列化的自定义类型。
    conf.registerKryoClasses(Array(classOf[StringPojo]))
    val context = new SparkContext(conf)
    val lineRdd = context.textFile("E:\\sourceData\\maptest.txt")
//    lineRdd.distinct()
    val wordsRdd=lineRdd.map{line =>
      val words=line.split("\t")
      new StringPojo(words(0),words(1))
    }

    val pairRdd1= wordsRdd.map(pojo=>(pojo.name+pojo.secondName,1))
    pairRdd1.reduceByKey(_+_).foreach(println)
   val pairRdd= wordsRdd.map(pojo=>(pojo.name+pojo.secondName,pojo))
    pairRdd.reduceByKey((x,y)=>x).map(_._2).foreach(println)

//    pairRdd.distinct().foreach(println)
//    val distRdd=wordsRdd.distinct()
//    distRdd.foreach(println)

  }


实体类:

class StringPojo(val name:String,val secondName:String) {
  override def toString: String = {
    super.toString
    this.name + "|" + this.secondName

  }

  override def hashCode(): Int = {
//    println("name:"+ this.secondName+",hashCode:"+ this.secondName.hashCode)
    this.secondName.hashCode
  }

}

实验结果:

(helloworld,2)
(hellospark,2)
(hellohive,2)


hello|spark
hello|world
hello|hive

上面的过程就是如何过滤rdd中重复的对象的过程了,但是我有一个疑问:String和我自定义的对象都是对象类型,为什么字符串可以直接调用distinct去重,而我自定义的确不行呢?一开始我以为是hashCode方法没有重写,但是重写了之后还是没有去重。但是我觉得自定义对象肯定也可以的,可能我漏了什么地方。


















©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值