Spark系列---SparkSQL动态与反射方式创建DataFrame(Java、Scala版本)

本文介绍两种将非JSON格式的RDD转换为DataFrame的方法:一种是推荐使用的动态创建Schema方式;另一种是通过反射的方式,但不推荐使用。文章详细展示了这两种方法的实现步骤,并提供了Scala和Java版本的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.动态创建Scheme将非json格式RDD转换成DataFrame,推荐
scala版本

package com.kevin.scala.dataframe
 
import org.apache.spark.sql.types._
import org.apache.spark.sql.{RowFactory, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
 
/**
  * 动态创建Scheme将非json格式RDD转换成DataFrame,推荐
  */
object DataFrameRDDWithStruct {
 
  def main(args: Array[String]): Unit = {
    // 1.创建sparkconf
    val conf = new SparkConf().setAppName("DataFrameRDDWithStruct").setMaster("local")
    // 2.创建sc
    val sc = new SparkContext(conf)
    // 3.创建sqlcontext
    val sqlContext = new SQLContext(sc)
    val line = sc.textFile("DTSparkSql\\src\\main\\resources\\person.txt")
    // 4.读取文件数据,先使用map切分数据,再使用map将数据转成Row类型
    val row = line.map(_.split(",")).map(s => RowFactory.create(s(0),s(1),Integer.valueOf(s(2))))
    // 5.动态构建DataFrame中的元数据,一般来说这里的字段可以源于字符串,也可以源于外部数据库
    val structFields = Array(
      StructField("id",StringType,true),
      StructField("name",StringType,true),
      StructField("age",IntegerType,true)
    )
    // 6.将list转为DataFrame中的元数据
    val structType = DataTypes.createStructType(structFields)
    // 7.将row类型的rdd数据和对应的字段名称类型转成DataFrame
    val df = sqlContext.createDataFrame(row,structType)
    // 8.查询数据
    df.show()
    // 9.将df转成rdd然后遍历获取name的数据
    df.rdd.foreach(r => println(r.getAs("name")))
    // 10.关闭sc
    sc.stop()
 
  }
 
}

java版本

package com.kevin.java.dataframe;
 
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
 
import java.util.Arrays;
import java.util.List;
 
/**
 * @author kevin
 * @version 1.0
 * @description     动态创建Scheme将非json格式RDD转换成DataFrame,推荐
 * @createDate 2019/1/6
 */
public class DataFrameRDDWithStruct {
 
    public static void main(String[] args) {
 
        // 1.创建SparkConf作业设置作业名称和模式
        SparkConf conf = new SparkConf().setAppName("DataFrameRDDWithStruct").setMaster("local");
 
        // 2.基于Sparkconf对象创建一个SparkContext上下文,它是通往集群的唯一通道,且在创建时会创建任务调度器
        JavaSparkContext sc = new JavaSparkContext(conf);
 
        // 3.根据sc创建SQLContext对象对sql进行分析处理
        SQLContext sqlContext = new SQLContext(sc);
 
        // 4.读取文件数据
        String file = "DTSparkSql\\src\\main\\resources\\person.txt";
        JavaRDD<String> lineRDD = sc.textFile(file);
 
        // 5.转成Row类型的RDD
        JavaRDD<Row> rowJavaRDD = lineRDD.map(new Function<String, Row>() {
            @Override
            public Row call(String line) throws Exception {
                String[] s = line.split(",");
                return RowFactory.create(s[0], s[1], Integer.valueOf(s[2]));
            }
        });
 
        // 6.动态构建DataFrame中的元数据,一般来说这里的字段可以源于字符串,也可以源于外部数据库
        List<StructField> structFields = Arrays.asList(
                DataTypes.createStructField("id", DataTypes.StringType, true),
                DataTypes.createStructField("name", DataTypes.StringType, true),
                DataTypes.createStructField("age", DataTypes.IntegerType, true));
 
        // 7.将list转为DataFrame中的元数据
        StructType structType = DataTypes.createStructType(structFields);
 
        // 8.将row类型的rdd数据和对应的字段名称类型转成DataFrame
        DataFrame df = sqlContext.createDataFrame(rowJavaRDD, structType);
 
        // 9.查询前20行数据
        df.show();
 
        // 10.将DataFrame转为RDD
        JavaRDD<Row> javaRDD = df.javaRDD();
 
        // 11.遍历rdd数据
        javaRDD.foreach(new VoidFunction<Row>() {
            @Override
            public void call(Row row) throws Exception {
                System.out.println((String)row.getAs("name"));
            }
        });
 
        // 12.关闭
        sc.close();
 
    }
}

2.通过反射的方式将非json格式的RDD转换成DataFrame,不推荐使用
scala版本

package com.kevin.scala.dataframe
 
import org.apache.spark.sql.SQLContext
import org.apache.spark.{SparkConf, SparkContext}
 
/**
  * 通过反射的方式将非json格式的RDD转换成DataFrame,不推荐使用
  */
object DataFrameRDDWithReflect {
 
  def main(args: Array[String]): Unit = {
    // 1.创建sparkconf
    val conf = new SparkConf().setAppName("DataFrameRDDWithReflect").setMaster("local")
    // 2.创建sc
    val sc = new SparkContext(conf)
    // 3.创建sqlcontext
    val sqlContext = new SQLContext(sc)
    // 4.导入隐饰操作,否则RDD无法调用toDF方法
    import sqlContext.implicits._
    val line = sc.textFile("DTSparkSql\\src\\main\\resources\\person.txt")
    // 5.读取文件用map切分,再用map将数据装成Person类型,toDF转成DataFrame
    val df = line.map(_.split(",")).map(p => new Person(p(0),p(1),p(2).trim.toInt)).toDF
    // 6.注册成临时表
    df.registerTempTable("person")
    // 7.查询id=2的数据
    sqlContext.sql("select * from person where id = 2").show()
    // 8.将df转成rdd,map将数据封装到person中
    val map = df.rdd.map(r => new Person(r.getAs("id"),r.getAs("name"),r.getAs("age")))
    // 9.遍历person的数据
    map.foreach(println(_))
    // 10.关闭sc
    sc.stop
  }
 
}

java版本

package com.kevin.java.dataframe;
 
import com.kevin.java.entity.Person;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SQLContext;
 
/**
 * @author kevin
 * @version 1.0
 * @description     通过反射的方式将非json格式的RDD转换成DataFrame,不推荐使用
 * @createDate 2019/1/6
 */
public class DataFrameRDDWithReflect {
 
    public static void main(String[] args) {
 
        // 1.创建SparkConf作业设置作业名称和模式
        SparkConf conf = new SparkConf().setAppName("DataFrameRDDWithReflect").setMaster("local");
 
        // 2.基于Sparkconf对象创建一个SparkContext上下文,它是通往集群的唯一通道,且在创建时会创建任务调度器
        JavaSparkContext sc = new JavaSparkContext(conf);
 
        // 3.根据sc创建SQLContext对象对sql进行分析处理
        SQLContext sqlContext = new SQLContext(sc);
 
        // 4.读取文件数据
        String file = "DTSparkSql\\src\\main\\resources\\person.txt";
        JavaRDD<String> lineRDD = sc.textFile(file);
 
        // 5.获取每一行txt数据转为person类型
        JavaRDD<Person> personRDD = lineRDD.map(new Function<String, Person>() {
            @Override
            public Person call(String line) throws Exception {
                String[] s = line.split(",");
                Person p = new Person();
                p.setId(s[0]);
                p.setName(s[1]);
                p.setAge(Integer.valueOf(s[2]));
                return p;
            }
        });
 
        // 6.传入Person的时候,sqlContext是通过反射的方式创建DataFrame
        // 在底层通过反射的方式获得Person的所有field,结合RDD本,就生成了DataFrame
        DataFrame df = sqlContext.createDataFrame(personRDD, Person.class);
 
        // 7.将DataFrame注册成表
        df.registerTempTable("person");
 
        // 8.查询id=2的数据
        DataFrame sql = sqlContext.sql("select id,name,age from person where id=2");
        sql.show();
 
        // 9.将DataFrame转成RDD并用row.getAs("列名")获取数据
        JavaRDD<Row> javaRDD = df.javaRDD();
        JavaRDD<Person> map = javaRDD.map(new Function<Row, Person>() {
            @Override
            public Person call(Row row) throws Exception {
                Person p = new Person();
                p.setId((String) row.getAs("id"));
                p.setName((String) row.getAs("name"));
                p.setAge((Integer) row.getAs("age"));
                return p;
            }
        });
 
        // 10.遍历数据
        map.foreach(new VoidFunction<Person>() {
            @Override
            public void call(Person person) throws Exception {
                System.out.println(person);
            }
        });
 
        // 11.关闭
        sc.close();
 
 
    }
}
### 关于Spark算子在Scala版本中的文档和实例 在处理数据集时,Apache Spark提供了丰富的操作符(operators),这些可以分为转换(transformations)和动作(actions)。对于不同的Scala版本支持情况,在Spark 2.0之后,默认构建已切换到使用Scala 2.11而非之前的Scala 2.10[^2]。 #### 转换操作符 (Transformations) 转换操作符用于定义新的分布式集合。常见的有`map`, `filter`, `flatMap`, 和 `groupByKey`等: ```scala val numbers = spark.sparkContext.parallelize(1 to 10) // 使用 map 进行简单映射变换 val squaredNumbers = numbers.map(x => x * x) ``` #### 动作操作符 (Actions) 一旦通过一系列转换创建了一个RDD或DataFrame/Dataset,则可以通过执行动作来触发计算并获取结果。常用的动作包括`collect()`, `count()`, `take(n)`: ```scala println(squaredNumbers.collect().mkString(", ")) ``` #### DataFrame API 示例 随着Spark SQL的发展,推荐更多地采用DataFrame API来进行数据分析工作,这不仅因为其性能优化更好,而且语法更加直观易懂: ```scala import org.apache.spark.sql.SparkSession val spark = SparkSession.builder.appName("example").getOrCreate() import spark.implicits._ val df = Seq((1, "a"), (2, "b")).toDF("id", "value") df.show() ``` 上述代码展示了如何利用DataFrame API读取序列化数据源,并将其展示出来。值得注意的是,虽然这里使用的例子基于较新版本Scala编写,但是由于Spark兼容多个主要版本之间的差异较小,因此大多数情况下无需担心跨不同次要版本间的移植性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值