Spark SQL 中UDF的讲解

Spark SQL 中UDF的讲解

User Define Function, 用户自定义函数,简称UDF,存在与很多组件中。

在使用 Sparksql的人都遇到了 Sparksql所支持的函数太少了的难处,除了最基本的函数, Sparksql所能支撑的函数很少,肯定不能满足正常的项目使用, UDF可以解决问题。

SparkSQL中的UDF相当于是11出,UDAF相当于是多进一出,类似于聚合函数。

开窗函数一般分组取topn时常用。

可以理解为自己定义函数,来获取自己想要的结果!
案例借鉴于网络!
需求:计算文本中每一个单词的长度!
代码:
Scala版本:
package com.bynear.Scala

import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}

object UDF {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("SparkSQL_UDF").setMaster("local")
    val sc = new SparkContext(conf)
    val sqlContext = new SQLContext(sc)
    val names = Array("刘亦菲", "张柏芝", "冯提模","陈一发儿")
    val nameRDD = sc.parallelize(names, 5)
    val nameRowRDD = nameRDD.map(name => Row(name))
    val structType = StructType(Array(StructField("name", StringType, true)))
    val namesDF = sqlContext.createDataFrame(nameRowRDD, structType)
    namesDF.registerTempTable("names")
    sqlContext.udf.register("strLen", (str: String) => str.length)
    sqlContext.sql("select name,strLen(name) as length from names").show()
    sqlContext.sql("select name,strLen(name) as length from names").collect().foreach(println)

  }
}
运行结果:
+----+------+
|name|length|
+----+------+
| 刘亦菲|     3|
| 张柏芝|     3|
| 冯提模|     3|
|陈一发儿|     4|
+----+------+

[刘亦菲,3]
[张柏芝,3]
[冯提模,3]
[陈一发儿,4]

Java版本:
package com.bynear.spark_sql;

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.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.api.java.UDF1;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import java.util.ArrayList;
public class JavaUDF {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName("JavaUDF").setMaster("local");
        JavaSparkContext sc = new JavaSparkContext(conf);
        SQLContext sqlContext = new SQLContext(sc.sc());
        ArrayList names = new ArrayList();
        names.add("刘亦菲");
        names.add("张柏芝");
        names.add("冯提模");
        names.add("陈一发儿");
        JavaRDD nameRDD = sc.parallelize(names);
        JavaRDD nameRowRDD = nameRDD.map(new Function, Row>() {
            @Override
            public Row call(String line) throws Exception {
                return RowFactory.create(String.valueOf(line));
            }
        });
        /**
         * 使用动态编程方式,将RDD转换为Dataframe
         */
        ArrayList fields = new ArrayList();
        fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
        StructType structType = DataTypes.createStructType(fields);
        DataFrame nameDF = sqlContext.createDataFrame(nameRowRDD, structType);
        /**
         * 注册临时表
         */
        nameDF.registerTempTable("user");
        /**
         * 根据UDF函数参数的个数来决定是实现哪一个UDF  UDF1UDF2, 表明包含几个参数传入
         * UDF1, Integer> 表示 传入参数 String 输出参数为 Integer
         * call方法为 自定义的函数!
         * DataTypes.IntegerType  必须与输出参数的类型一致即 Integer
         */
        sqlContext.udf().register("StrLen", new UDF1, Integer>() {
            @Override
            public Integer call(String s) throws Exception {
                return s.length();
            }
        }, DataTypes.IntegerType);
        /**
         * select name ,StrLen(name) as length from user
         * 在临时表user中 查找name   StrLen(name) == name的长度
         * StrLen(name) as length 表示将获取到的name的长度 例如15  15作为一列 as length 列名为 length
         */
        sqlContext.sql("select name ,StrLen(name) as length from user").show();
        Row[] rows = sqlContext.sql("select name ,StrLen(name) as length from user").collect();
        for (Row row : rows) {
            System.out.println(row);
        }


        sc.close();
    }
}
输出结果: 同上!

Java版本中,主要之一到UDFX 方法,以及传入参数的个数类型,以及输出类型,最终要的是文本最后的
DataTypes.IntegerType  类型要与输出类型相同!





你可能感兴趣的:(Spark)