spark rdd

1. 基础环境搭建

  • 日志级别设置:Logger.getLogger("org").setLevel(Level.OFF) 关闭 Spark 冗余日志,便于查看业务输出;
  • Spark 上下文创建:Spark 2.0+ 优先通过SparkSession构建,再通过spark.sparkContext获取Sc(SparkContext),本地模式配置master("local"),指定应用名appName("xxx")

2. RDD 核心分类

  • 普通 RDD:元素为单一类型(Int、String 等),支持基础的过滤、映射、集合运算;
  • 键值对 RDD(Pair RDD):元素为(key, value)二元组,支持 ByKey 系列专属操作,是分布式聚合、分组的核心载体。

3. 数据处理通用流程

从实战代码中提炼出通用 RDD 数据处理流程:RDD创建 → 数据清洗 → 数据转换/合并/运算 → 数据筛选 → 结果输出(如违章记录处理:读取 HDFS 文件 → 去表头清洗 → union 合并 → map 切分 + filter 筛选 → 格式化打印)

二、 核心 RDD 函数分类总结(按功能归类,含详细说明)

按 RDD 操作类型和功能场景,将所有涉及的函数分为RDD 创建函数行动操作函数普通转换操作函数键值对 RDD 专属函数四大类,清晰呈现每个函数的用途、特性和示例。

1. RDD 创建函数

用于生成 RDD,是所有 RDD 操作的基础,支持内存集合、外部文件、RDD 转换三种来源。

函数名 功能描述 适用场景 代码示例
parallelize 将本地集合(List/Array)并行化,生成 RDD;元素可单一类型或二元组(键值对) 本地小数据测试、快速构建 RDD sc.parallelize(List(1,2,3))(普通 RDD);sc.parallelize(List(("Tom",82)))(键值对 RDD)
textFile 读取外部文本文件(本地路径 / HDFS 路径),每行文本作为 RDD 一个元素,返回RDD[String] 读取日志、数据文件等文本数据 sc.textFile("hdfs://master:8020/spark/data/record.txt")(读取 HDFS 文件)
zip 拉链函数:将两个同分区、同元素数量的 RDD 合并为键值对 RDD(第一个 RDD 为 key,第二个为 value) 两个关联 RDD 绑定为键值对 rdd4.zip(rdd5)(将 "五岳名称" 与 "对应山脉" 合并为键值对 RDD)

2. 行动操作函数

立即触发 Spark 作业计算(非懒加载),返回本地数据(非 RDD),用于取值、打印、结果输出等场景。

函数名 功能描述 返回类型 特性 / 注意事项 代码示例
take(n) 获取 RDD 中前 n 个元素 本地 Array 数组 可遍历打印,适用于预览少量数据 intRdd.take(3)(获取前 3 个元素,返回Array[Int]
first() 获取 RDD 的第一个元素,等价于take(1)(0) 单个元素(与 RDD 元素类型一致) 简化获取首个元素的操作 recordA.first()(获取文件表头行);intRdd.first()(获取首个数值元素)
foreach 分布式遍历 RDD 中所有元素,执行自定义逻辑(如打印、写入存储) 无返回值(Unit) 行动操作,触发计算;区别于本地数组的foreach rdd2.foreach(println)(打印 RDD 所有元素);result.foreach(x=>{格式化打印})
lookup(key) 键值对 RDD 专属:根据指定 key 查找所有对应的 value Seq(序列) 无需全量遍历,查询效率较高 rdd6.lookup("东岳")(查找 "东岳" 对应的 value "泰山")

3. 普通转换操作函数

懒加载(仅记录逻辑,不立即计算),返回新的 RDD,适用于所有类型 RDD,核心用于数据清洗、映射、集合运算等。

函数名 功能描述 输入输出关系 关键特性 代码示例
filter 接收布尔类型匿名函数,保留返回true的元素,过滤掉false的元素 多对少(元素数量≤原 RDD) 不改变元素类型,仅筛选元素 rdd1.filter(x=>x%2==0)(筛选偶数);rdd3.filter(x=>x._2>=60)(筛选及格成绩)
map 一对一转换:对每个元素执行自定义逻辑,输入一个元素,输出一个元素 一对一(元素数量 = 原 RDD) 可改变元素类型,保留嵌套结构 intRdd.map(x=>x+1)(数值 + 1);strRdd.map(x=>x.toUpperCase())(字符串转大写)
flatMap 一对多转换:先执行 map 逻辑,再对结果进行扁平化展开(拆解嵌套结构) 一对多(元素数量≥原 RDD) 拆解数组 / 集合等嵌套结构,核心区别于 map strRdd2.flatMap(x=>x.split(" "))(切分字符串并拆解数组,获取单个单词)
union 合并两个同类型 RDD,求并集 元素数量 = 两个 RDD 元素之和 不自动去重,是唯一不去重的集合运算 cleanA.union(cleanB)(合并两个清洗后的违章记录 RDD)
intersection 求两个同类型 RDD 的交集,仅保留同时存在于两个 RDD 中的元素 元素数量≤两个 RDD 的最小值 自动去重,会触发 Shuffle rdd5.intersection(rdd6)(获取 rdd5 和 rdd6 的共同元素)
subtract 求差集:A.subtract (B) 保留属于 A 但不属于 B 的元素 元素数量≤原 RDD(A)的元素数量 自动去重,会触发 Shuffle rdd5.subtract(rdd6)(获取 rdd5 有但 rdd6 没有的元素)
distinct 对单个 RDD 进行去重,移除重复元素 元素数量≤原 RDD 会触发 Shuffle,适用于去重需求 rdd6.distinct()(去掉 rdd6 中的重复元素 2)

4. 键值对 RDD 专属函数

仅适用于元素为(key, value)二元组的 Pair RDD,是分布式分组、聚合、排序的核心函数,按功能再细分三类。

(1) 基础取值函数

函数名 功能描述 返回类型 代码示例
keys 提取键值对 RDD 中所有的 key,生成仅包含 key 的普通 RDD RDD(key 类型) rdd6.keys(提取五岳名称 key)
values 提取键值对 RDD 中所有的 value,生成仅包含 value 的普通 RDD RDD(value 类型) rdd6.values(提取山脉名称 value)

(2) ByKey 核心函数(分组 / 聚合 / 排序)

函数名 功能描述 关键特性 代码示例
groupByKey 按 key 进行分组,同一 key 的所有 value 封装到CompactBuffer(Spark 可变数组)中 仅分组,不做聚合;性能低于reduceByKey rdd10.groupByKey()(按 "水果 / 蔬菜" 分组,聚合对应商品)
reduceByKey 先按 key 分组,再对每组的 value 执行归约计算(求和、最大值等) 分组 + 聚合;有预聚合,性能更优 rdd14.reduceByKey((a,b)=>a+b)(按 key 对 value 求和)
sortByKey 按 key 进行排序,默认升序(true),传入false为降序 按 key 有序排列,支持数值 / 字符串排序 rdd12.sortByKey(false)(按 key 降序排序)

(3) 仅处理 Value 的函数

函数名 功能描述 关键特性 代码示例
mapValues 仅对键值对 RDD 的 value 进行自定义转换,key 保持不变 无需手动处理 key,比普通 map 更简洁 rdd16.mapValues(x=>x*0.6)(value 乘以 0.6,key 自动保留)

三、 核心函数关键区别与避坑指南

  1. map vs flatMap:核心区别是是否保留嵌套结构map保留数组 / 集合嵌套,flatMap拆解嵌套;
  2. groupByKey vs reduceByKeyreduceByKey有预聚合(Map 端聚合),性能优于groupByKey(仅 Shuffle 后聚合),优先使用reduceByKey做分组聚合;
  3. 集合运算函数:union不自动去重,intersection/subtract自动去重,且后两者会触发 Shuffle,大数据量使用需谨慎;
  4. 字符串比较:筛选数据时,优先用equals()(如x.equals(firstA)),而非==/!=,避免分布式环境下对象引用判断错误;
  5. 索引区别:数组索引从 0 开始,元组索引从 1 开始(x._1/x._2),避免取错元素。

例子:

java 复制代码
package bigdata2403

import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession

object Weizhang {
  def main(args: Array[String]): Unit = {
    //1.设置日志级别
    Logger.getLogger("org").setLevel(Level.OFF)
    //2.创建SparkSession对象
    val spark = SparkSession
      .builder()
      .appName("rdd5")
      .master("local")
      .getOrCreate()
    //3.SparkContext对象的获取
    val sc = spark.sparkContext
    /*
    查找违章3次以上的车辆
    分析:
    1.读取数据文件,创建RDD数据集---textFile
    2.去掉表头
      (1)获取第一个元素---first
      (2)筛选出不是第一个元素的数据---filter
    3.对每个rdd元素做切分操作---map(split)
    4.转换为键值对RDD---map
    (车牌号,1)---(x(2),1)
    5.每个车辆的违章次数---reduceByKey
    (Mu0066,3)
    6.筛选出次数大于3的记录---filter(x=>x._2>3)
     */
    //1.读取数据文件,创建RDD数据集---textFile
    val record = sc.textFile("D:\\spark\\data\\record.txt")
    //2.去掉表头
    val recordFirst = record.first()
    val recordWithoutHead = record.filter(x=> !x.equals(recordFirst))
    //3.对每个rdd元素做切分操作---map(split)
    val recordSplit = recordWithoutHead.map(x=>x.split("\t"))
    //4.转换为键值对RDD---map
    val recordMerge = recordSplit.map(x=>(x(2),1))
    //5.每个车辆的违章次数---reduceByKey
    val recordCount = recordMerge.reduceByKey((a,b)=>a+b)
    //6.筛选出次数大于3的记录---filter(x=>x._2>3)
    val result = recordCount.filter(x=>x._2>3)
    //7.打印输出结果:车牌号:【CZ8462】,违章次数:【6】次
    result.foreach(x=>println("车牌号:【"+x._1+"】,违章次数:【"+x._2+"】次"))
  }
}
相关推荐
STLearner2 小时前
2025时空数据研究工作总结
大数据·人工智能·python·深度学习·学习·机器学习·智慧城市
Sui_Network2 小时前
Sui 2025 年终回顾:支付、BTC 与机构采用篇
大数据·人工智能·物联网·web3·去中心化·区块链
前端世界2 小时前
鸿蒙分布式通信安全实践:中间人攻击原理与防御实现
分布式·华为·harmonyos
无限大.2 小时前
为什么“微服务“架构流行?——从集中式到分布式
分布式·微服务·架构
小股虫2 小时前
打造跨服务数据的“可信视图”:实验效果报表的架构演进
大数据·分布式·微服务·架构·报表·团队建设
Albert.H.Holmes2 小时前
Elasticsearch学习
大数据·学习·elasticsearch
TDengine (老段)2 小时前
TDengine GROUP BY 与 PARTITION BY 使用及区别深度分析
大数据·开发语言·数据库·物联网·时序数据库·tdengine·涛思数据