UDFを継承したクラスではなく、GenericUDFを継承するともっといい感じになるようだ。(今回の場合)
ということで、前回作成したArrayStringToStringUDF
をStringなArrayでなくても良いように改変してみる。
GenericUDF
を継承したArrayToObjectUDF
クラスを作成する。
GenericUDF
を継承した場合、基本的には以下の2つのメソッドのオーバーライドで機能を実現する。
initialize
UDFに与えられた引数の確認(数や型)と戻り値のObjectInspector返却を行うメソッド。
@Override
public ObjectInspector initialize(ObjectInspector[] args)
throws UDFArgumentException {
if(args.length != 2){
throw new UDFArgumentException("_FUNC_ expects exactly 2 arg");
}
if(args[0].getCategory() != Category.LIST){
throw new UDFArgumentException("The 1st arg needs to be array but an arg of type "+ args[0].getTypeName() + " was given.");
}
if(!(args[1] instanceof IntObjectInspector)){
throw new UDFArgumentException("The 2nd arg needs to be integer but an arg of type "+ args[1].getTypeName() + " was given.");
}
listOI = (ListObjectInspector)args[0];
intOI = (IntObjectInspector)args[1];
GenericUDFUtils.ReturnObjectInspectorResolver returnOI = new GenericUDFUtils.ReturnObjectInspectorResolver(true);
returnOI.update(listOI.getListElementObjectInspector());
converter = ObjectInspectorConverters.getConverter(listOI.getListElementObjectInspector(), returnOI.get());
return returnOI.get();
}
引数の数、引数の型など確認。今回はARRAYの中身は問わないので、args[0]に関してはCategoryの確認のみとなっている。
listOI(ListObjectInspector)
とintOI(IntObjectInspector)
はクラスのメンバ変数として定義しており、evaluate
で値の取得に使用する。
また、converter(Converter)
もクラスメンバとして定義しており、evaluate
で値の返却に利用する。
evaluate
実際にUDFへ渡された引数を元に値の返却を行うメソッド。
@Override
public Object evaluate(DeferredObject[] args) throws HiveException {
if(args.length != 2){
return null;
}
if(args[0].get() == null){
return null;
}
if(listOI == null || intOI == null){
throw new HiveException("Invalid ObjectInspector.");
}
List<?> values = (List<?>)(listOI.getList(args[0].get()));
int num = intOI.get(args[1].get());
if(values == null || values.size() < num + 1){
return null;
}
return converter.convert(values.get(num));
}
引数が2である事を確認して、ARRAYの確認とinitialize時に取得しているはずのObjectInspectorの確認をした後に、Listから該当箇所のObjectをgetしてConverterでconvertして返却。
出来た!これでINTなARRAYもSTRINGなARRAYもSTRUCTなARRAYも怖くない!
注)と言いつつSTRUCTなARRAYは試していません、、、大丈夫かな(汗)
いや、まぁこの手の事はHiveがネイティブでサポートしてくれるのが一番良いと思うのだけども、そんなに需要が無いのかなぁ(-_-)