import java.util.*;
public class FuncUtil {
//校验表达式
public static Map<String, Object> checkFunc(String expression) {
Map<String, Object> map = new HashMap<String, Object>();
String str = formatFunc(expression);
String reg = "^[A-Z()&+-]+$";
map.put("expression", str);
map.put("isvalid", str.matches(reg));
return map;
}
//表达式格式化
private static String formatFunc(String expression) {
return expression.replaceAll("(", "(").replaceAll(")", ")")
.replaceAll(" ", "").replaceAll(" ", "").replaceAll("&&", "&")
.toUpperCase();
}
public static List<String> cal(String expression, Map<String, List<String>> dataMap) throws Exception {
Stack<OperatorEnum> opStack = new Stack<OperatorEnum>();
Stack<List<String>> dataStack = new Stack<List<String>>();
char[] charArr;
int length = (charArr = expression.toCharArray()).length;
char value;
OperatorEnum stackOp;
OperatorEnum currOp;
for (int i=0; i<length;) {
value = charArr[i];
//数据,操作符入栈
//操作符为字母
if (Character.isLetter(value)) {
String key = String.valueOf(value);
try {
List<String> item = (List)dataMap.get(key);
dataStack.push(new ArrayList<String>(item));
++i;
} catch (Exception e) {
throw new ExpressionFormatException("集合" + key +"不存在");
}
} else if (OperatorEnum.isSimpleOperator(String.valueOf(value))){
//考虑括号和优先级
//左括号或者当前操作数优先级比上一个操作数优先级高,操作数入栈,不做计算
if (!OperatorEnum.RIGHT_BRACKET.equals(currOp = OperatorEnum.getOperator(String.valueOf(value)))
&& (opStack.isEmpty() || OperatorEnum.LEFT_BRACKET.equals(stackOp = opStack.peek())
|| stackOp.getPriority() < currOp.getPriority())) {
opStack.push(currOp);
++i;
} else {
singleCal(opStack, dataStack);
if (OperatorEnum.RIGHT_BRACKET.equals(currOp)) {
while(!OperatorEnum.LEFT_BRACKET.equals(opStack.peek())) {
singleCal(opStack, dataStack);
}
if (!OperatorEnum.LEFT_BRACKET.equals(opStack.pop())) {
throw new ExpressionFormatException("解析异常");
}
++i;
}
}
} else {
throw new ExpressionFormatException("公式计算异常");
}
}
while (!opStack.isEmpty()) {
singleCal(opStack, dataStack);
}
return dataStack.pop();
}
private static void singleCal(Stack<OperatorEnum> opStack, Stack<List<String>> dataStack) throws ExpressionFormatException{
OperatorEnum currOp = opStack.peek();
if (OperatorEnum.LEFT_BRACKET.equals(currOp)) {
return ;
}
opStack.pop();
List<String> firstList = null;
List<String> secondList = null;
if (currOp.getParaNum() == 1) {
firstList = dataStack.pop();
} else {
secondList = dataStack.pop();
firstList = dataStack.pop();
}
List<String> result;
switch(currOp) {
case ADD: result = add(firstList,secondList); break;
case SUB: result = sub(firstList, secondList); break;
case AND: result = and(firstList, secondList); break;
default: throw new ExpressionFormatException("未实现的运算符[" + currOp + "]");
}
dataStack.push(result);
}
private static List<String> add(List<String> firstList, List<String> secondList) {
if (firstList == null) {
return new ArrayList<String>();
}
if (secondList == null) {
return firstList;
}
firstList.removeAll(secondList);
firstList.addAll(secondList);
return firstList;
}
private static List<String> sub(List<String> firstList, List<String> secondList) {
if (firstList == null) {
return new ArrayList<String>();
}
if (secondList == null) {
return firstList;
}
firstList.removeAll(secondList);
return firstList;
}
private static List<String> and(List<String> firstList, List<String> secondList) {
if (firstList == null || secondList == null) {
return new ArrayList<String>();
}
firstList.retainAll(secondList);
return firstList;
}
}
public enum OperatorEnum {
ADD("+", 2, 1, "加法"),
SUB("-", 2, 1, "减法"),
AND("&", 2, 1, "交集"),
LEFT_BRACKET("(", 0, Integer.MAX_VALUE, "左括号"),
RIGHT_BRACKET(")", 0, Integer.MAX_VALUE, "右括号");
private String expression;
private int paraNum;
private int priority;
private String desc;
OperatorEnum(String expression, int paraNum, int priority, String desc) {
this.expression = expression;
this.paraNum = paraNum;
this.priority = priority;
this.desc = desc;
}
//是否简单二元运算
public static boolean isSimpleOperator(String expression) {
return ADD.expression.equals(expression) || SUB.expression.equals(expression) || AND.expression.equals(expression)
|| LEFT_BRACKET.expression.equals(expression) || RIGHT_BRACKET.expression.equals(expression);
}
public static OperatorEnum getOperator(String expression) {
for (OperatorEnum operator : OperatorEnum.values()) {
if (operator.expression.equals(expression)) {
return operator;
}
}
return null;
}
public String getExpression() {
return expression;
}
public void setExpression(String expression) {
this.expression = expression;
}
public int getParaNum() {
return paraNum;
}
public void setParaNum(int paraNum) {
this.paraNum = paraNum;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}