PageRank

复制代码
package com.shujia.spark.core

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

object Demo19PageRank {
  def main(args: Array[String]): Unit = {

    val conf: SparkConf = new SparkConf()
      .setAppName("pagerank")
      .setMaster("local")

    val sc = new SparkContext(conf)

    //读取数据
    val pagerank: RDD[String] = sc.textFile("data/pagerank.txt")


    //整理数据,给每个网页一个初始的pr值

    var pageRDD: RDD[(String, List[String], Double)] = pagerank.map(line => {
      val split: Array[String] = line.split(" ")
      //当前网页
      val page: String = split(0)
      //出链列表
      val list: List[String] = split(1).split(",").toList

      (page, list, 1.0)
    })

    //网页编号和出链列表
    val pageListRDD: RDD[(String, List[String])] = pageRDD.map(kv => (kv._1, kv._2))

    //阻尼系数
    val Q = 0.85

    //网页的数量
    val N: Long = pageRDD.count()

    var flag = true

    while (flag) {

      //将网页的pr值平方给出链列表
      val avgPageRDD: RDD[(String, Double)] = pageRDD.flatMap {
        case (page: String, list: List[String], pr: Double) =>

          val avgPr: Double = pr / list.size

          list.map(p => (p, avgPr))
      }

      //计算新的pr值
      var nowPrRDD: RDD[(String, Double)] = avgPageRDD
        .reduceByKey(_ + _)
        .mapValues(pr => (1 - Q) / N + Q * pr) //增加阻尼系数


      //将每个网页的出链列表关联回去
      val joinRDD: RDD[(String, (Double, List[String]))] = nowPrRDD.join(pageListRDD)

      //整理数据
      val resultRDD: RDD[(String, List[String], Double)] = joinRDD.map {
        case (page: String, (pr: Double, list: List[String])) =>
          (page, list, pr)
      }

      /**
        * 计算每个网页新的pr值和上一次pr值,差值的平均值
        *
        */

      //上一次网页的pr值
      val lastPrRDD: RDD[(String, Double)] = pageRDD.map(kv => (kv._1, kv._3))

      //计算网页pr 差值
      val prJoinRDD: RDD[(String, (Double, Double))] = nowPrRDD.join(lastPrRDD)

      val prChaRDD: RDD[Double] = prJoinRDD.map {
        case (page: String, (noePr: Double, lastPr: Double)) =>
          Math.abs(lastPr - noePr)
      }
      //计算差值平均值
      val avgPr: Double = prChaRDD.sum() / prChaRDD.count()

      println("差值平均值:" + avgPr)

      //如果差值平均值小于阈值,跳出循环
      if (avgPr < 0.001) {
        flag = false
      }

      //第二次计算使用第一次的结果
      pageRDD = resultRDD
    }

    pageRDD.foreach(println)

  }

}
复制代码

 

posted @   坤坤无敌  阅读(319)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示