在Spark中,也支持Hive中的自定义函数。自定义函数大致可以分为三种:

UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等
UDAF(User- Defined Aggregation Funcation),用户自定义聚合函数,类似在group by之后使用的sum,avg等
UDTF(User-Defined Table-Generating Functions),用户自定义生成函数,有点像stream里面的flatMap
自定义一个UDF函数需要继承UserDefinedAggregateFunction类,并实现其中的8个方法

示例

import org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types.{DataType, StringType, StructField, StructType}

object GetDistinctCityUDF extends UserDefinedAggregateFunction{
  /**
    * 输入的数据类型
    * */
  override def inputSchema: StructType = StructType(
    StructField("status",StringType,true) :: Nil
  )
  /**
    * 缓存字段类型
    * */
  override def bufferSchema: StructType = {
    StructType(
      Array(
        StructField("buffer_city_info",StringType,true)
      )
    )
  }
/**
  * 输出结果类型
  * */
  override def dataType: DataType = StringType
/**
  * 输入类型和输出类型是否一致
  * */
  override def deterministic: Boolean = true
/**
  * 对辅助字段进行初始化
  * */
  override def initialize(buffer: MutableAggregationBuffer): Unit = {
    buffer.update(0,"")
  }
/**
  *修改辅助字段的值
  * */
  override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
    //获取最后一次的值
    var last_str = buffer.getString(0)
    //获取当前的值
    val current_str = input.getString(0)
    //判断最后一次的值是否包含当前的值
    if(!last_str.contains(current_str)){
      //判断是否是第一个值,是的话走if赋值,不是的话走else追加
      if(last_str.equals("")){
        last_str = current_str
      }else{
        last_str += "," + current_str
      }
    }
    buffer.update(0,last_str)

  }
/**
  *对分区结果进行合并
  * buffer1是机器hadoop1上的结果
  * buffer2是机器Hadoop2上的结果
  * */
  override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
    var buf1 = buffer1.getString(0)
    val buf2 = buffer2.getString(0)
    //将buf2里面存在的数据而buf1里面没有的数据追加到buf1
    //buf2的数据按照,进行切分
    for(s <- buf2.split(",")){
      if(!buf1.contains(s)){
        if(buf1.equals("")){
          buf1 = s
        }else{
          buf1 += s
        }
      }
    }
    buffer1.update(0,buf1)
  }
/**
  * 最终的计算结果
  * */
  override def evaluate(buffer: Row): Any = {
    buffer.getString(0)
  }
}

注册自定义的UDF函数为临时函数

def main(args: Array[String]): Unit = {
    /**
      * 第一步 创建程序入口
      */
    val conf = new SparkConf().setAppName("AralHotProductSpark")
    val sc = new SparkContext(conf)
    val hiveContext = new HiveContext(sc)
  //注册成为临时函数
    hiveContext.udf.register("get_distinct_city",GetDistinctCityUDF)
  //注册成为临时函数
    hiveContext.udf.register("get_product_status",(str:String) =>{
      var status = 0
      for(s <- str.split(",")){
        if(s.contains("product_status")){
          status = s.split(":")(1).toInt
        }
      }
    })
}

Spark学习之路 (十九)SparkSQL的自定义函数UDF[转]的更多相关文章

  1. Spark学习之路 (十九)SparkSQL的自定义函数UDF

    在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...

  2. Spark(十三)SparkSQL的自定义函数UDF与开窗函数

    一 自定义函数UDF 在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_ ...

  3. Spark学习之路(九)—— Spark SQL 之 Structured API

    一.创建DataFrame和Dataset 1.1 创建DataFrame Spark中所有功能的入口点是SparkSession,可以使用SparkSession.builder()创建.创建后应用 ...

  4. Spark学习之路 (九)SparkCore的调优之数据倾斜调优

    摘抄自:https://tech.meituan.com/spark-tuning-pro.html 数据倾斜调优 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Sp ...

  5. Spark学习之路 (九)SparkCore的调优之数据倾斜调优[转]

    调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题--数据倾斜,此时Spark作业的性能会比期望差很多.数据倾斜调优,就是使用各种技术方案解决不同类型的数据倾斜问题,以保证Spark作业的 ...

  6. 嵌入式Linux驱动学习之路(十九)触摸屏驱动、tslib测试

    触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断, ...

  7. IOS学习之路十九(JSON与Arrays 或者 Dictionaries相互转换)

    今天写了个json与Arrays 或者 Dictionaries相互转换的例子很简单: 通过 NSJSONSerialization 这个类的 dataWithJSONObject: options: ...

  8. JavaWeb学习记录(十九)——jstl自定义标签库之传统标签

    一.传统标签 (1)JSP引擎将遇到自定义标签时,首先创建标签处理器类的实例对象,然后按照JSP规范定义的通信规则依次调用它的方法. public void setPageContext(PageCo ...

  9. JavaWeb学习记录(十九)——jstl自定义标签之简单标签

    一.简单标签共定义了5个方法: setJspContext方法 setParent和getParent方法 setJspBody方法 doTag方法 二.方法介绍 osetJspContext方法 用 ...

随机推荐

  1. learn about sqlserver partitition and partition table 1

    Dear all, Let get into business, the partitions on sql server is very different with that on oracle. ...

  2. Qt使用双缓冲绘图时报错:pure virtual method called

    这个问题折磨了我将近四个小时. 起始原因是想写一个双缓冲绘图的画板,大概看了一下网上的教程,理解双缓冲绘图的思想后,没有完全参照网上的步骤,想着用自己的思路实现一下.(其实和网上的教程也没有太大差别) ...

  3. geo常见需求

    常见的地理位置相关需求有: 1.查找附近的人 2.显示两点距离 3.点是否在指定范围内(地理围栏) redis.MongoDB.mysql都已支持geo 几种geo方案对比 https://blog. ...

  4. 使用GitHub+Travis-CI+Docker打造自动化流水线

    全文采用的是阿里云的ESC服务器,系统是CentOS 7 示例项目是NodeJS编写,本文主要是Docker的使用,在文章前2/3都是Docker命令介绍,最后我们会完成一个自动化的示例. 准备 注册 ...

  5. 学习Sparql

    一 . gstore--一种开源图数据库系统 https://www.docin.com/p-1951514687.html 二 . 使用 SPARQL 查询 RDF 数据 https://www.i ...

  6. [Redis-CentOS7]Redis字符串操作(二)

    登录Redis # redis-cli 127.0.0.1:6379> 添加字符串 EX 超期时间60s 127.0.0.1:6379> set username 'leoshi' OK ...

  7. 外部SRAM的种类

    外部SRAM注意事项 为使外部SRAM器件达到出最佳性能,建议遵循以下原则: 使用与连接的主系统控制器的接口数据带宽相同的SRAM. 如果管脚使用或板上空间的限制高于系统性能要求,可以使用较连接的控制 ...

  8. Leetcode:235. 二叉搜索树的最近公共祖先

    Leetcode:235. 二叉搜索树的最近公共祖先 Leetcode:235. 二叉搜索树的最近公共祖先 Talk is cheap . Show me the code . /** * Defin ...

  9. Leetcode字典树-720:词典中最长的单词

    第一次做leetcode的题目,虽然做的是水题,但是菜鸟太菜,刚刚入门,这里记录一些基本的知识点.大佬看见请直接路过. https://leetcode-cn.com/problems/longest ...

  10. 【转载】ibit-mybatis介绍

    原文链接:ibit-mybatis介绍 概述    ibit-mybatis是一个Mybatis的增强工具,在Mybatis的基础上增加了新的特性与功能,志在简化开发流程.提高开发效率. 特性 无侵入 ...