本文为您介绍如何通过Java UDF实现不同类型数值相除获取余数。

取余函数UDF说明

Integer UDFPMod(Long a, Long b)
  • 函数名:UDFPMod
  • 功能:返回a除以b的余数。
  • 参数说明:
    • a:INTEGER类型数值1。
    • b:INTEGER类型数值2。
Long UDFPMod(Long a, Long b)
  • 函数名:UDFPMod
  • 功能:返回a除以b的余数。
  • 参数说明:
    • a:LONG类型数值1。
    • b:LONG类型数值2。
Double UDFPMod(Long a, Long b)
  • 函数名:UDFPMod
  • 功能:返回a除以b的余数。
  • 参数说明:
    • a:DOUBLE类型数值1。
    • b:DOUBLE类型数值2。

UDF使用示例

  • 注册函数
    UDFPMod.java测试通过后,将其注册为函数使用。

    说明 一个UDF从发布到服务端供生产使用,需要经过打包、上传、注册这三个步骤。您可以使用一键发布功能一次性完成这些步骤(Studio会依次执行mvn clean package、上传Jar和注册UDF这三个步骤)。详情请参见打包、上传和注册
  • 使用示例
    成功注册UDF后,执行以下命令:
    • 示例一
      select pmodTest(-9L,-4L) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | -1  |
      +-----+
    • 示例二
      select pmodTest(9.0,-4.0) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | -3.0 |
      +-----+
    • 示例三
      select pmodTest(9,4) from dual;
      运行结果如下。
      +-----+
      | _c0 |
      +-----+
      | 1   |
      +-----+

UDF代码示例

  • UDF实现示例
    package com.aliyun.odps.examples.udf// package名称,可以根据您的情况定义。
    import com.aliyun.odps.udf.UDF;
    public class UDFPMod extends UDF {
        // 使用Long类型的数据。
        public String evaluate(Long  a,  Long  b)  {
            if  ((a  == null) || (b == null) || b==0L)  {
                return  null;
            }
            Long d=((a % b) + b) % b;
            return d.toString();
        }
        // 使用Double类型的数据。
        public String evaluate(Double a, Double b)  {
            if  ((a == null) || (b == null) || b==0.0)  {
                return  null;
            }
            Double d=((a % b) + b) % b;
            return d.toString() ;
        }
        // 使用Integer类型的数据。
        public String evaluate(Integer a, Integer b)  {
            if  ((a == null) || (b == null) || b==0)  {
                return  null;
            }
            Integer d=((a % b) + b) % b;
            return d.toString();
        }
    }
    说明 示例中为返回值类型做了toString处理,对测试结果无影响。
  • UDF单元测试
    package com.aliyun.odps.examples.udf// package名称,可以根据您的情况定义。
    import org.junit.Test;
    import static org.junit.Assert.assertEquals;
    public class TestUDFPMod {
        private UDFPMod udf = new UDFPMod();
        @Test
        public void test_null(){
            assertEquals(null, udf.evaluate(null, 1L));
            assertEquals(null, udf.evaluate(1L, null));
            assertEquals(null, udf.evaluate((Long)null, null));
    
            assertEquals(null, udf.evaluate(null, 1.0));
            assertEquals(null, udf.evaluate(1.0, null));
            assertEquals(null, udf.evaluate((Double)null, null));
        }
        @Test
        public void test_正常情况(){
            assertEquals(1L, udf.evaluate(9L, 4L));
            assertEquals(3L, udf.evaluate(-9L, 4L));
            assertEquals(-1L, udf.evaluate(-9L, -4L));
            assertEquals(-3L, udf.evaluate(9L, -4L));
            // 原来抛异常,现返回null。
            assertEquals(null, udf.evaluate(9L, 0L));
    
            assertEquals(1.0, udf.evaluate(9.0, 4.0));
            assertEquals(3.0, udf.evaluate(-9.0, 4.0));
            assertEquals(-1.0, udf.evaluate(-9.0, -4.0));
            assertEquals(-3.0, udf.evaluate(9.0, -4.0));
            // 原来返回Nan,现返回null。
            assertEquals(null, udf.evaluate(9.0, 0.0));
        }
    }