需求解决问题

当每次读取hive表或者其他数据源,获取数据,相对其进行rdd操作,遇到任何类都需要df.rdd(row>row.getstring(0))去获取,就很麻烦,所以可以实现个通用的转换方式

1.dataframe转为rdd通用方法

  /**
* df转为rdd 通用方法
*
* @param frame
* @return
*/
def dataFrameToRdd(frame: DataFrame): RDD[Array[Any]] = {
val fields: Array[StructField] = frame.schema.toArray
val zipData: Array[(StructField, Int)] = fields.zipWithIndex
val rdd: RDD[Array[Any]] = frame.rdd.map(row => {
val res: Array[Row => Any] = zipData.map(structField => squareRowkey2(structField._1, structField._2))
val array: Array[Any] = res.map(fun => {
val value = fun(row)
if (value == null) String.valueOf(value) else value
})
array
})
rdd
}

  对类型进行判断

/**
* 根据schema信息进行判断与封装
*
* @param dataType
* @return
*/
//封装rowkey
def squareRowkey2(dataType: (StructField, Int)): (Row) => Any = {
val (structField, index) = dataType
structField.dataType match {
case StringType =>
(row: Row) => if (row.isNullAt(index)) null else row.getString(index)
case LongType =>
(row: Row) =>if (row.isNullAt(index)) null else row.getLong(index)
case FloatType =>
(row: Row) => if (row.isNullAt(index)) null else row.getFloat(index)
case DoubleType =>
(row: Row) => if (row.isNullAt(index)) null else row.getDouble(index)
case IntegerType =>
(row: Row) => if (row.isNullAt(index)) null else row.getInt(index)
case BooleanType =>
(row: Row) => if (row.isNullAt(index)) null else row.getBoolean(index)
case DateType =>
(row: Row) => if (row.isNullAt(index)) null else row.getDate(index)
case TimestampType =>
(row: Row) => if (row.isNullAt(index)) null else row.getTimestamp(index)
case BinaryType =>
(row: Row) => if (row.isNullAt(index)) null else row.getAs[Array[Byte]](index)
case ArrayType(elementType, containsNull) =>
(row: Row) => {
val value: mutable.WrappedArray[_ >: Integer with String <: io.Serializable with Comparable[_ >: Integer with String]] = elementType match {
case IntegerType => {
row.getAs[mutable.WrappedArray[Integer]](index)
}
case StringType => {
row.getAs[mutable.WrappedArray[String]](index)
}
case _ => row.getAs[mutable.WrappedArray[String]](index)
}
//这儿必须转换为java的list 防止map转json字符串不符合要求
if (value == null) {
util.Collections.emptyList()
}
JavaConversions.bufferAsJavaList(value.toBuffer)
}
case StructType(fields) =>
(row: Row) => row.getAs[mutable.Map[String, String]](index)
case _ =>
(row: Row) => row.getString(index)
}
}

 二、rdd转实体对象

大多数是都是讲数据分装为case calss或者对象

  def  dataFrameToEntity [U: ClassTag] (frame: DataFrame, clazz: Class[U], hiveRdd: RDD[Array[Any]]) = {
val fields: Array[StructField] = frame.schema.toArray
val rdd = hiveRdd.map(array => {
val map = new util.HashMap[String, Any]()
fields.map(_.name).zip(array)
.foreach {
case (k, v) => (map.put(k, v))
}
val str = GsonUtil.toJsonString(map)
//这边转换工具类 就是gson的转为对象的方法
val value: U = GsonUtil.GsonToBean(str, clazz)
value
})
rdd
}

 使用:

    lazy val df: DataFrame =spark.read.table("user")
//将df转为rdd实体类
val userRdd: RDD[Array[Any]] = RddUtils.dataFrameToRdd(df)
val userRDD2: RDD[User] = RddUtils.dataFrameToEntity(df, classOf[User], userRdd)

  

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils; import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; /**
* @ClassName: com.xxx.sbc.dw.spark.submit.service.GsonUtil
* @Description: json工具类
* @Author: imp
* @Time: 2020/10/23 10:01
* @Version: 1.0
*/ public class GsonUtil { private static Gson gson = null; //判断gson对象是否存在了,不存在则创建对象
static {
if (gson == null) {
//gson = new Gson(); //当使用GsonBuilder方式时属性为空的时候输出来的json字符串是有键值key的,显示形式是"key":null,而直接new出来的就没有"key":null的
gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
}
} //无参的私有构造方法
private GsonUtil() {
} /**
* 将对象转成json格式
*
* @param object
* @return String
*/
public static String GsonString(Object object) {
String gsonString = null;
if (gson != null) {
gsonString = gson.toJson(object);
}
return gsonString;
} /**
* 将json转成特定的cls的对象
*
* @param gsonString
* @param cls
* @return
*/
public static <T> T GsonToBean(String gsonString, Class<T> cls) {
T t = null;
if (StringUtils.isNotEmpty(gsonString)) {
//传入json对象和对象类型,将json转成对象
t = JSONObject.parseObject(gsonString, cls);
}
return t;
} /**
* json字符串转成list
*
* @param gsonString
* @param cls
* @return
*/
public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
List<T> list = null;
if (gson != null) {
//根据泛型返回解析指定的类型,TypeToken<List<T>>{}.getType()获取返回类型
list = gson.fromJson(gsonString, new TypeToken<List<T>>() {
}.getType());
}
return list;
} /**
* json字符串转成list中有map的
*
* @param gsonString
* @return
*/
public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(gsonString,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
} public static <T> List<Map<String, T>> gsonToListMaps(String str) {
List<Map<String, T>> list = null;
if (gson != null) {
list = gson.fromJson(str,
new TypeToken<List<Map<String, T>>>() {
}.getType());
}
return list;
} /**
* json字符串转成map的
*
* @param gsonString
* @return
*/
public static <T> Map<String, String> GsonToMaps(String gsonString) {
Map<String, String> map = null;
if (gson != null) {
map = gson.fromJson(gsonString, new TypeToken<Map<String, String>>() {
}.getType());
}
return map;
} /**
* 判断是否是json
*
* @param object
* @return
*/
public static Boolean isJson(Object object) {
try {
gson.toJson(object);
return true;
} catch (Exception e) {
System.err.format("{} is not json", object.toString());
return false;
}
} /**
* 对象转为json字符串
*
* @param o
* @return
*/
public static String toJsonString(Object o) {
return JSON.toJSONString(o, SerializerFeature.DisableCircularReferenceDetect);
} /**
* json转为map
*
* @param json
* @return
*/
public static Map<String, String> jsonToMap(String json) {
return JSON.parseObject(json, new TypeReference<LinkedHashMap<String, String>>() {
});
} public static Map<String, Object> entityToMap(Object obj) throws IllegalAccessException {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Class<?> clazz = obj.getClass();
System.out.println(clazz);
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
String fieldName = field.getName();
Object value = field.get(obj);
if (value == null) {
value = "";
}
map.put(fieldName, value);
}
return map;
}

  

 

Spark的dataframe转rdd通用工具类的更多相关文章

  1. spark下dataframe转为rdd格式

    dataframe可以实现很多操作,但是存储到本地的时候,只能存 parquest格式 需要存储源格式,需要转换为rdd类型 将dataframe中的每一行都map成有逗号相连的string,就变为了 ...

  2. Spark SQL概念学习系列之DataFrame与RDD的区别

    不多说,直接上干货! DataFrame的推出,让Spark具备了处理大规模结构化数据的能力,不仅比原有的RDD转化方式更加简单易用,而且获得了更高的计算性能.Spark能够轻松实现从MySQL到Da ...

  3. spark是怎么从RDD升级到DataFrame的?

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark专题的第五篇,我们来看看DataFrame. 用过Python做过机器学习的同学对Python当中pandas当中的Data ...

  4. [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子

    [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子 from pyspark.sql.types import * schema = Struct ...

  5. [Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子

    [Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子 sqlContext = HiveContext(sc) peopleDF = sqlContext. ...

  6. [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子

    [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...

  7. 【spark】dataframe常见操作

    spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...

  8. 小白学习Spark系列四:RDD踩坑总结(scala+spark2.1 sql常用方法)

    初次尝试用 Spark+scala 完成项目的重构,由于两者之前都没接触过,所以边学边用的过程大多艰难.首先面临的是如何快速上手,然后是代码调优.性能调优.本章主要记录自己在项目中遇到的问题以及解决方 ...

  9. Spark 并行计算模型:RDD

    Spark 允许用户为driver(或主节点)编写运行在计算集群上,并行处理数据的程序.在Spark中,它使用RDDs代表大型的数据集,RDDs是一组不可变的分布式的对象的集合,存储在executor ...

随机推荐

  1. 动态svg图片简单制作

    一.简介 #topics #no-box-shadow-img { box-shadow: none } 博主头像 svg图片格式不同于其它图片格式,svg图片本质上是一个xml文件,它内部是标记语言 ...

  2. 学习JUC源码(2)——自定义同步组件

    前言 在之前的博文(学习JUC源码(1)--AQS同步队列(源码分析结合图文理解))中,已经介绍了AQS同步队列的相关原理与概念,这里为了再加深理解ReentranLock等源码,模仿构造同步组件的基 ...

  3. Newbe.ObjectVisitor 0.4.4 发布,模型验证器上线

    Newbe.Claptrap 0.4.4 发布,模型验证器上线. 更新内容 完全基于表达式树的模型验证器 本版本,我们带来了基于表达式树实现的模型验证器.并实现了很多内置的验证方法. 我们罗列了与 F ...

  4. python冒泡算法联系代码

    root@(none):~/python# python maopao.py[6, 11, 13, 22, 99]root@(none):~/python# cat maopao.py #!/usr/ ...

  5. 第 5篇 Scrum 冲刺博客

    一.站立式会议 1.站立式会议照片 2.昨天已完成的工作 售货员页面功能 3.今天计划完成的工作 添加登录系统账号密码数据库模块 继续对商品销售部分进行编码 职工管理页面 4.工作中遇到的困难 ①页面 ...

  6. 没有它你的DevOps是玩不转的,你信不?

    摘要:架构的选择对于DevOps的实践是至关重要的,从某种程度上来说,架构就是DevOps这场战役的粮草,它是支撑着DevOps成功落地的重要前提. 善用兵者,役不再籍,粮不三载.取用于国,因粮于敌, ...

  7. 【复习笔记】重习 AC 自动机

    发现已经忘了许多....于是复习一下 基础要点概况 AC 自动机基于 Trie 树 的结构,即构建 AC 自动机前需要先建 Trie. 一个状态中除了转移 \(\delta\) 之外还有失配指针 \( ...

  8. USB接口禁用小工具v1.0.1

    由论坛用户原创制作的一个USB接口工具, 可选择手动/自动启动或者禁止启动模式, 开启禁止启动模式后USB接口将关闭识别功能, 有效防止U盘设备侵入,对于机房实验室设施来说相当管用. 下载地址:htt ...

  9. 安卓qq视频动态名片制作器

    本软件来自互联网,仅供个人参考,严禁商业用途! 非常炫酷的diy动态名片教程,B格绝对高,内含软件教程代码,包会!

  10. masterha_check_repl --conf=/etc/mha/app1.cnf检查错误

    [mysql@node3 ~]$ masterha_check_repl --conf=/etc/mha/app1.cnf Tue Jul 7 22:43:26 2020 - [warning] Gl ...