Spark的dataframe转rdd通用工具类
需求解决问题
当每次读取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通用工具类的更多相关文章
- spark下dataframe转为rdd格式
dataframe可以实现很多操作,但是存储到本地的时候,只能存 parquest格式 需要存储源格式,需要转换为rdd类型 将dataframe中的每一行都map成有逗号相连的string,就变为了 ...
- Spark SQL概念学习系列之DataFrame与RDD的区别
不多说,直接上干货! DataFrame的推出,让Spark具备了处理大规模结构化数据的能力,不仅比原有的RDD转化方式更加简单易用,而且获得了更高的计算性能.Spark能够轻松实现从MySQL到Da ...
- spark是怎么从RDD升级到DataFrame的?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark专题的第五篇,我们来看看DataFrame. 用过Python做过机器学习的同学对Python当中pandas当中的Data ...
- [Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子
[Spark][Python][RDD][DataFrame]从 RDD 构造 DataFrame 例子 from pyspark.sql.types import * schema = Struct ...
- [Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子
[Spark][Python][DataFrame][RDD]DataFrame中抽取RDD例子 sqlContext = HiveContext(sc) peopleDF = sqlContext. ...
- [Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子
[Spark][Python][DataFrame][RDD]从DataFrame得到RDD的例子 $ hdfs dfs -cat people.json {"name":&quo ...
- 【spark】dataframe常见操作
spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...
- 小白学习Spark系列四:RDD踩坑总结(scala+spark2.1 sql常用方法)
初次尝试用 Spark+scala 完成项目的重构,由于两者之前都没接触过,所以边学边用的过程大多艰难.首先面临的是如何快速上手,然后是代码调优.性能调优.本章主要记录自己在项目中遇到的问题以及解决方 ...
- Spark 并行计算模型:RDD
Spark 允许用户为driver(或主节点)编写运行在计算集群上,并行处理数据的程序.在Spark中,它使用RDDs代表大型的数据集,RDDs是一组不可变的分布式的对象的集合,存储在executor ...
随机推荐
- java课后作业2019.11.04
一.编写一个程序,指定一个文件夹,能够自动计算出其总容量 1.代码 package HomeWork; import java.io.File; public class getFileDaxiao ...
- Javascrip之BOM
重点内容 理解windows对象-BOM核心 控制窗口.框架.弹出窗口 利用location对象中的页面信息 利用navigator对象了解浏览器 BOM:浏览器对象模型[Browner Object ...
- csv文件的写操作
import csv sumbmit_csv_path = "submit_have_valid_SGD.csv" with open(sumbmit_csv_path, &quo ...
- 题解-CF1444C Team-Building
题面 CF1444C Team-Building 给 \(n\) 个点 \(m\) 条边,每个点有颜色 \(c_i(1\le c_i\le k)\),求有多少个颜色对两组点并后是二分图. 数据范围:\ ...
- Java并发编程的艺术(十)——线程池
线程池的作用 降低资源消耗.重复利用已有线程,减少线程的创建和销毁造成的消耗. 提高响应速度.当有任务需要处理的时候,就不用再花费重新创建线程的时间了. 提高线程的可管理性.不合理利用线程,会浪费资源 ...
- 一、Nginx笔记--linux下载安装部署Nginx
Nginx 到底是什么? Nginx 是⼀个⾼性能的HTTP和反向代理web服务器,核⼼特点是占有内存少,并发能⼒强 Nginx ⼜能做什么事情(应⽤场景) Http服务器(Web服务器) 性能⾮常 ...
- SpringBoot异步调用--@Async详解
1. 概述 在日常开发中,为了提高主线程的效率,往往需要采用异步调用处理,例如系统日志等.在实际业务场景中,可以使用消息中间件如RabbitMQ.RocketMQ.Kafka等来解决.假如对高可用 ...
- JavaSE11-多态&抽象类&接口
1.多态 1.1 多态的概述 什么是多态 同一个对象,在不同时刻表现出来的不同形态 多态的前提 要有继承或实现关系 要有方法的重写 要有父类引用指向子类对象 1.2 多态中的成员访问特点 成员访问特点 ...
- Linux 设置日期时间
linux 日期设置 直接设置日期和时间 date -s 2019-02-11 date -s 12:12:12 date -s "2019-02-11 12:12:12"
- Flink连接器-批处理-读写Hbase
Flink批处理与hbase的读写 source-hbase 父类 是模仿官方写的. import org.apache.flink.api.common.io.LocatableInputSplit ...