前几天有个spark 任务特别的慢,原因是我写了一个udf,把一个对象作为构造函数的对象穿进去了
这个udf的功能是为了实现,把传入的数学表达式(如:20*x/(20-x)),和传入的列的值做计算,把传入的列的值替换成x
刚开始的想法就是直接用java提供的方法,就是开篇所说的,结果几十万的数据跑半小时,后面就放弃了
最终做法就是,直接在udf写计算方法,也是网上参考了一位同行的
我计算的都是double
@Override
public Double call(Double thisv, String expstr) throws Exception {
Double result=null;
expstr = expstr.replace("x", String.valueOf(thisv));
try {
result = calculate(transfer(expstr));
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static String transfer(String mathStr) {
// 标记输出结果
StringBuilder result = new StringBuilder();
StringBuilder ysfresult = new StringBuilder();
// 1.初始化一个运算符栈。
Stack<Character> stack = new Stack();
if (mathStr == null || mathStr.length() == 0) {
return null;
}
System.out.println("--------------");
System.out.println("中缀表达式:" + mathStr);
boolean belong_isnum = true;//前一个是否是数字
char[] arr = mathStr.toCharArray();
for (int i = 0; i < arr.length; i++) {
// 2.从算数表达式输入的字符串中依次从左向右每次读取一个字符。
char s = arr[i];
// 3.如果当前字符是操作数,则直接填写到后缀表达式。
if (!Character.isDigit(s) && s != '.') {
belong_isnum = false;
}
if (Character.isDigit(s) || s == '.') {
if (belong_isnum) {
result.append(s);
} else {
result.append("|" + s);
}
belong_isnum = true;
}
// 4.如果当前字符是(左括号,将其压入运算符栈(第一步定义)。
else if ('(' == s) {
stack.push(s);
}
// 5.如果当前字符为运算符,则
else if ('+' == s || '-' == s || '*' == s || '/' == s) {
if (!stack.isEmpty()) {
char stackTop = stack.pop();
// 当此运算符的优先级高于栈顶元素的时候,则将此运算符压入运算符栈
if (compare(s, stackTop)) {
stack.push(stackTop);
stack.push(s);
}
// 否则,弹出栈顶运算符到后缀表达式,并且将当前运算符压栈。回到步骤2.
else {
result.append("|"+stackTop);
stack.push(s);
}
}
// 5.1.当运算符栈为空,则将其压入运算符栈。
else {
stack.push(s);
}
}
// 6.如果当前字符是)右括号,反复将栈顶元素弹出到后缀表达式,直到栈顶元素是左括号(为止,并将左括号从栈中弹出丢弃。
else if (s == ')') {
while (!stack.isEmpty()) {
char item = stack.pop();
if (item != '(') {
result.append(item);
} else {
break;
}
}
}
}
result.insert(result.length() - 1, "|");
while (!stack.isEmpty()) {
ysfresult.append("|" + stack.pop());
}
result.append(ysfresult);
System.out.println("后缀表达式:" + result.toString());
return result.toString();
}
//比较优先级
private static boolean compare(char s, char item) {
if (item == '(') {
return true;
}
if (s == '*' || s == '/') {
if (item == '+' || item == '-') {
return true;
}
}
return false;
}
private static Double calculate(String transferToPostfix) {
Stack<Double> stack = new Stack();
// char[] c = transferToPostfix.toCharArray();
String[] c = transferToPostfix.split("\\|");
Double a, b;
for (int i = 0; i < c.length; i++) {
switch (c[i]) {
case "+":
a = Double.parseDouble(stack.pop().toString());
b = Double.parseDouble(stack.pop().toString());
stack.push(b + a);
break;
case "-":
a = Double.parseDouble(stack.pop().toString());
b = Double.parseDouble(stack.pop().toString());
stack.push(b - a);
break;
case "*":
a = Double.parseDouble(stack.pop().toString());
b = Double.parseDouble(stack.pop().toString());
stack.push(b * a);
break;
case "/":
a = Double.parseDouble(stack.pop().toString());
b = Double.parseDouble(stack.pop().toString());
stack.push(b / a);
break;
default:
String d = c[i];
try {
stack.push(Double.parseDouble(d));
} catch (NumberFormatException e) {//33333.0*
}
break;
}
}
return stack.pop();
}
}
网友评论