Spark综合实例

RDD实现单词计数

Scala(Spark Shell)方法

如果你在 spark-shell(Scala 环境)中运行:

1. 启动 Spark Shell

spark-shell

(确保 Spark 已安装,PATH 配置正确)

2. 执行单词统计

// 1. 读取文件(确保路径正确!)
val lines = sc.textFile("file:///home/xdt/桌面/data.txt")

// 2. 拆分单词 + 统计
val wordCounts1 = lines.flatMap(line => line.split(" "))  // 按空格分割
val wordCounts2 = wordCounts1.map(word => (word, 1))           // 每个单词计数 1
val wordCounts3 = wordCounts2.reduceByKey(_ + _)               // 相同单词累加

// 3. 显示结果(前20个)
wordCounts3.take(20).foreach(println)

// 4. 保存结果
wordCounts3.saveAsTextFile("file:///home/xdt/桌面/wordcount_output")

3. 检查输出

  • 控制台:会打印前 20 个单词的统计结果。

  • 文件:结果保存在 ~/桌面/wordcount_output/part-00000

注意路径写法,要写自己电脑上的路径。

上面是文件来源于本地的情况,如果文件位于HDFS里,要先把HDFS启动起来。

印象里好像是start-all.sh

scala是一种多范式编程语言,结合了面向对象编程(OOP)和函数式编程(FP)的特性。

设计初衷是为了解决Java冗长性的问题,同时兼容JVM(java虚拟机)。

Scala提供了比Java更纯粹的FP体验。


RDD是弹性分布式数据集。是Apache Spark的核心数据结构,或者说一个数据集合。

RDD的操作类型有两种:转换操作(生成新RDD,不执行)、行动操作(触发实际计算并返回结果)。

RDD是不可变的,一旦被创建,不可修改,只能通过转换操作生成新的RDD。

还有一些词:血缘、分片多节点并行计算。慢慢研究~~

分布式:

分布式计算笔记(一) - 快乐星猫i - 博客园(分布式笔记)

Spark - 快乐星猫i - 博客园(Spark基础RDD)

RDD - 快乐星猫i - 博客园(RDD编程基础)

Spark SQL - 快乐星猫i - 博客园(Spark SQL)

Spark MLib - 快乐星猫i - 博客园(Spark的机器学习)

IntelliJ IDEA 中运行

1. 安装必要工具

  • IntelliJ IDEA(建议使用 Ultimate 版,Community 版也支持 Scala)

  • Scala 插件(在 IDEA 中安装)

  • JDK 8/11(Spark 3.x 支持 JDK 8/11)

  • Scala SDK(建议 2.12.x,与 Spark 3.x 兼容)

2. 创建 Scala 项目

可以通过plugin下载scala,来创建scala项目

步骤 1:打开 IDEA,新建项目
  1. File → New → Project

  2. 选择 ScalaIDEA(或 SBT 项目)

  3. 设置:

    • Project SDK:选择 JDK(如 JDK 11)

    • Scala SDK:点击 "Create" 按钮,选择 Scala 版本(如 2.12.15)

不要忘记导Scala SDK!!!

步骤 2:配置项目结构
  • 项目名称:SparkWordCount

  • 项目路径:选择你的工作目录

3. 添加 Spark 依赖

方法 1:使用 SBT(推荐)

1.在项目根目录下找到 build.sbt 文件,添加以下内容:

name := "SparkWordCount"
version := "1.0"
scalaVersion := "2.12.15"

libraryDependencies += "org.apache.spark" %% "spark-core" % "3.3.0"

2.等待 IDEA 自动加载依赖(或手动点击 Reload All SBT Projects)。

确保 Scala 版本匹配(Spark 3.3.0 需要 Scala 2.12.x)

方法 2:手动添加 JAR

1.下载 Spark 的预编译包:

wget https://archive.apache.org/dist/spark/spark-3.3.0/spark-3.3.0-bin-hadoop3.tgz
tar -xzf spark-3.3.0-bin-hadoop3.tgz

2.在 IDEA 中:

  • File → Project Structure → Libraries → + → Java

  • 添加 Spark 的 JAR 文件:

    • spark-3.3.0-bin-hadoop3/jars/*.jar

这里主包直接添加的炸包 下面是主包的spark的路径

/opt/spark-3.5.5-bin-hadoop3/jars/spark-core_2.12-3.5.5.jar

否则无法导入 org.apache.spark

4. 创建 WordCount 程序

步骤 1:新建 Scala 类
  1. 右键 src/main/scalaNew → Scala Class

  2. 输入名称 WordCount,类型选择 Object

步骤 2:编写代码
import org.apache.spark.{SparkConf, SparkContext}

object WordCount {
  def main(args: Array[String]): Unit = {
    // 1. 创建 Spark 配置
    val conf = new SparkConf()
      .setAppName("WordCount")
      .setMaster("local[*]")  // 本地模式

    // 2. 初始化 SparkContext
    val sc = new SparkContext(conf)

    try {
      // 3. 读取文件(替换为你的路径)
      val lines = sc.textFile("file:///home/xdt/桌面/data.txt")

      // 4. 单词统计
      val wordCounts = lines
        .flatMap(_.split(" "))
        .map((_, 1))
        .reduceByKey(_ + _)

      // 5. 打印结果
      wordCounts.take(20).foreach(println)

      // 6. 保存结果
      wordCounts.saveAsTextFile("file:///home/xdt/桌面/wordcount_output")
    } finally {
      // 7. 关闭 SparkContext
      sc.stop()
    }
  }
}

5. 运行程序

方法 1:直接运行
  1. 右键 WordCount.scalaRun 'WordCount'

  2. 查看控制台输出和结果文件。

方法 2:打包后提交
  1. File → Project Structure → Artifacts → + → JAR → From modules

  2. 选择主类为 WordCount,构建 JAR。

  3. 通过 spark-submit 运行:

spark-submit --class WordCount SparkWordCount.jar

计算图书每天平均销量

idea中运行Scala

object BookSalesAverage {
  def main(args: Array[String]): Unit = {
    // 输入数据
    val sales = List(("spark", 2), ("hadoop", 6), ("hadoop", 4), ("spark", 6))
    
    // 计算每种图书的平均销量
    val averages = sales
      .groupBy(_._1)  // 按图书名称分组
      .map { case (book, salesList) =>
        val values = salesList.map(_._2)  // 提取销量值
        val avg = values.sum.toDouble / values.size  // 计算平均值
        (book, avg)
      }
    
    // 打印结果
    averages.foreach { case (book, avg) =>
      println(s"$book 的平均销量: $avg")
    }
  }
}

代码说明:

  1. 输入数据:使用元组列表存储图书名称和销量数据

  2. 分组操作groupBy(_._1) 按图书名称(元组的第一个元素)分组

  3. 计算平均值

    • 对每个分组提取销量值(map(_._2)

    • 计算总和并除以数量得到平均值

  4. 输出结果:打印每种图书的平均销量

建表并查询(Spark SQL入门)

代码

import org.apache.spark.sql.{SparkSession, DataFrame}
import org.apache.spark.sql.types._

object SparkSQL {
  def main(args: Array[String]): Unit = {
    // Create SparkSession
    val spark = SparkSession.builder()
      .appName("DefineSchemaExample")
      .master("local[*]") // Remove this line for cluster execution
      .getOrCreate()

    try {
      // Define schema programmatically
      val schema = StructType(Array(
        StructField("Id", IntegerType, nullable = false),
        StructField("First", StringType, nullable = false),
        StructField("Last", StringType, nullable = false),
        StructField("Url", StringType, nullable = false),
        StructField("Published", StringType, nullable = false),
        StructField("Hits", IntegerType, nullable = false),
        StructField("Campaigns", ArrayType(StringType), nullable = false)
      ))

      // Read JSON file with the defined schema
      val blogsDF = spark.read.schema(schema).json("file:///home/xdt/桌面/blogs.json")

      // Show the DataFrame
      blogsDF.show()

      // Print schema
      blogsDF.printSchema()

      // Alternative way to print schema
      println(blogsDF.schema)

    } finally {
      spark.stop()
    }
  }
}

blogs.json

{"Id": 1,"First": "John","Last": "Doe","Url": "https://example.com/john","Published": "2023-01-15","Hits": 1024,"Campaigns": ["winter_sale", "new_user"]}
{"Id": 2,"First": "Jane","Last": "Smith","Url": "https://example.com/jane","Published": "2023-02-20","Hits": 2048,"Campaigns": ["spring_promo", "referral"]}
{"Id": 3,"First": "Bob","Last": "Johnson","Url": "https://example.com/bob","Published": "2023-03-10","Hits": 512,"Campaigns": ["summer_sale", "loyalty"]}
{"Id": 4,"First": "Alice","Last": "Williams","Url": "https://example.com/alice","Published": "2023-04-05","Hits": 4096,"Campaigns": ["back_to_school", "clearance"]}

一行数据放一行,不要换行。

运行结果 

Top统计

项目结构

TopNCalculator.scala

import scala.io.Source
import scala.util.{Failure, Success, Try}

object TopNCalculator {

  case class Order(orderId: Int, userId: Int, payment: Int, productId: Int)

  def calculateTopNPayments(filePaths: List[String], n: Int): List[Int] = {
    // 读取所有文件并合并数据
    val orders = filePaths.flatMap(readOrdersFromFile)

    // 按payment降序排序并取前N个
    orders
      .sortBy(-_.payment) // 降序排序
      .take(n)            // 取前N个
      .map(_.payment)     // 提取payment值
  }

  private def readOrdersFromFile(filePath: String): List[Order] = {
    Try {
      Source.fromResource(filePath)
        .getLines()
        .filter(_.trim.nonEmpty) // 过滤空行
        .flatMap { line =>
          line.split(",").map(_.trim) match {
            case Array(orderId, userId, payment, productId) =>
              Some(Order(
                orderId.toInt,
                userId.toInt,
                payment.toInt,
                productId.toInt
              ))
            case _ => None // 忽略格式不正确的行
          }
        }
        .toList
    } match {
      case Success(orders) => orders
      case Failure(ex) =>
        println(s"Error reading file $filePath: ${ex.getMessage}")
        List.empty[Order]
    }
  }
}

Main.scala

object Main extends App {
  // 文件路径(放在resources目录下)
  val filePaths = List("file1", "file2")

  // 计算Top 5 payment值
  val topN = 5
  val topPayments = TopNCalculator.calculateTopNPayments(filePaths, topN)

  // 打印结果
  println(s"Top $topN payment values:")
  topPayments.zipWithIndex.foreach { case (payment, index) =>
    println(s"${index + 1}. $payment")
  }
}

file1.txt

1,1768,50,155
2,1218,600,211
3,2239,788,242
4,3101,28,599
5,4899,290,129
6,3110,54,1201
7,4436,259,877
8,2369,7890,27

file2.txt

100,4287,226,233
101,6562,489,124
102,1124,33,17
103,3267,159,179
104,4569,57,125
105,1438,37,116

运行结果

统计M&M巧克力豆(Scala)

package main.scala

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._

/**
 * 用法: MnMcount <mnm_file_dataset>
 */
object MnMcount {
  def main(args: Array[String]) {
    val spark = SparkSession
      .builder
      .appName("MnMCount")
      .master("local[*]")
      .getOrCreate()

    if (args.length < 1) {
      print("Usage: MnMcount <mnm_file_dataset>")
      sys.exit(1)
    }
    // 获取M&M豆数据集的文件名
    val mnmFile = args(0)
    // 将文件读入Spark DataFrame
    val mnmDF = spark.read.format("csv")
      .option("header", "true")
      .option("inferSchema", "true")
      .load(mnmFile)
    // 用groupBy()按州和颜色分组,然后聚合求出所有颜色的总计数
    // 使用orderBy()降序排列
    val countMnMDF = mnmDF
      .select("State", "Color", "Count")
      .groupBy("State", "Color")
      .agg(count("Count").alias("Total"))
      .orderBy(desc("Total"))
    // 展示所有州和颜色对应的聚合结果
    countMnMDF.show(60)
    println(s"Total Rows = ${countMnMDF.count()}")
    println()
    // 通过过滤得到加利福尼亚州的聚合数据
    val caCountMnMDF = mnmDF
      .select("State", "Color", "Count")
      .where(col("State") === "CA")
      .groupBy("State", "Color")
      .agg(count("Count").alias("Total"))
      .orderBy(desc("Total"))
    // 展示加利福尼亚州的聚合结果
    caCountMnMDF.show(10)
    // 停止SparkSession
    spark.stop()
  }
}

项目文件夹下运行这个👇

spark-submit --class main.scala.MnMcount out/artifacts/MnMcount_jar/MnMcount.jar file:///home/xdt/桌面/mnm_daset.csv

运行结果

Spark SQL使用

读数据->创建临时视图->SQL查询

import org.apache.spark.sql.SparkSession

object SparkSQLDataLoadingExample {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession
      .builder
      .appName("SparkSQLExampleApp")
      .master("local[*]")  // 本地模式,使用所有可用核心
      .getOrCreate()

    // 数据集的路径
    val csvFile = "file:///home/xdt/桌面/LearningSparkV2-master/databricks-datasets/learning-spark-v2/flights/departuredelays.csv"

    // 读取数据并创建临时视图
    // 推断表结构 (注意, 如果文件较大, 最好手动指定表结构)
    val df = spark.read.format("csv")
      .option("inferSchema", "true")
      .option("header", "true")
      .load(csvFile)
    // 创建临时视图
    df.createOrReplaceTempView("us_delay_flights_tbl")

    //手动指定表结构
    val schema = "data STRING, delay INT, distance INT, origin STRING, destination STRING"

    spark.sql("""SELECT distance, origin, destination FROM us_delay_flights_tbl WHERE distance > 1000 ORDER BY distance DESC""").show(10)
  }
}

运行结果

MLlib机器学习库

查找出所有包含"spark"的句子,即将包含"spark"的句子 的标签设为1,没有"spark"的句子的标签设为0。

Scala代码

import org.apache.spark.ml.feature.{Tokenizer, HashingTF}
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.ml.Pipeline
import org.apache.spark.sql.SparkSession

object LogisticRegressionExample {
  def main(args: Array[String]): Unit = {
    // 1. 创建 SparkSession
    val spark = SparkSession.builder()
      .appName("SparkMLExample")
      .master("local[*]")  // 本地模式运行
      .getOrCreate()

    import spark.implicits._

    // 2. 准备训练数据
    val training = Seq(
      (0, "a b c d e spark", 1.0),
      (1, "b d", 0.0),
      (2, "spark f g h", 1.0),
      (3, "hadoop mapreduce", 0.0)
    ).toDF("id", "text", "label")

    // 3. 特征工程
    val tokenizer = new Tokenizer()
      .setInputCol("text")
      .setOutputCol("words")

    val hashingTF = new HashingTF()
      .setInputCol("words")
      .setOutputCol("features")
      .setNumFeatures(1000)  // 设置特征哈希的维度

    // 4. 定义逻辑回归模型
    val lr = new LogisticRegression()
      .setMaxIter(10)
      .setRegParam(0.01)

    // 5. 构建 Pipeline
    val pipeline = new Pipeline()
      .setStages(Array(tokenizer, hashingTF, lr))

    // 6. 训练模型
    val model = pipeline.fit(training)

    // 7. 准备测试数据
    val test = Seq(
      (4, "spark i j k"),
      (5, "l m n"),
      (6, "spark hadoop spark"),
      (7, "apache hadoop")
    ).toDF("id", "text")

    // 8. 预测
    val predictions = model.transform(test)
    predictions.select("text", "probability", "prediction").show()

    // 关闭 SparkSession
    spark.stop()
  }
}

运行结果

python代码

from pyspark.ml.feature import Tokenizer, HashingTF
from pyspark.ml.classification import LogisticRegression
from pyspark.ml import Pipeline

# 1. 数据准备(已经包含标签)
training = spark.createDataFrame([
    (0, "a b c d e spark", 1.0),
    (1, "b d", 0.0),
    (2, "spark f g h", 1.0),
    (3, "hadoop mapreduce", 0.0)
], ["id", "text", "label"])

# 2. 特征工程
tokenizer = Tokenizer(inputCol="text", outputCol="words")
hashingTF = HashingTF(inputCol="words", outputCol="features")

# 3. 定义模型(逻辑回归)
lr = LogisticRegression(maxIter=10, regParam=0.01)

# 4. 构建Pipeline
pipeline = Pipeline(stages=[tokenizer, hashingTF, lr])

# 5. 训练模型(这里才会用到.fit())
model = pipeline.fit(training)  # <-- 这里调用.fit()

# 6. 预测
test = spark.createDataFrame([
    (4, "spark i j k"),
    (5, "l m n"),
    (6, "spark hadoop spark"),
    (7, "apache hadoop")
], ["id", "text"])

prediction = model.transform(test)
prediction.select("text", "probability", "prediction").show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值