本次结对开发主要是要开发一个可以用于四则运算调用的接口
实现功能:JaxbUtil.java
package com.core.util; import java.io.StringReader; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import com.core.bean.Option; public class JaxbUtil { //javabean转换成xml private static String converToXml(Object obj,String encoding) { String result = null; try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller marshaller = context.createMarshaller(); //是否格式化xml(按标签自动换行) marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); //设置编码方式 marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding); StringWriter writer = new StringWriter(); marshaller.marshal(obj, writer); result = writer.toString(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return result; } public static String convertTomXml(Object object) { return converToXml(object, "UTF-8"); } //xml转换成javabean @SuppressWarnings("unchecked") public static<T> T convertToJavaBean(String xml,Class<T> c) { T t = null; try { JAXBContext context = JAXBContext.newInstance(c); Unmarshaller unmarshaller = context.createUnmarshaller(); t = (T)unmarshaller.unmarshal(new StringReader(xml)); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } return t; } public static void main(String[] args) { Option option = new Option(); option.setOperation_num(4); option.setMin(-1000); option.setMax(1000); option.setPoint_long(2); // System.out.println(convertTomXml(option)); String xml = convertTomXml(option); Option option2=convertToJavaBean(xml, Option.class); System.out.println(option2.getMin()+"~"+option2.getMax()); } }
计算功能:
package com.core.bean; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.core.util.JaxbUtil; public class Calculate { private static final Pattern EXPRESSION_PATTERN = Pattern.compile("[0-9\.+-/*()= ]+"); private static final Map<String,Integer> OP_PRIORITY_MAP = new HashMap<String ,Integer>() { /** * */ private static final long serialVersionUID = -5028404412583819744L; { put("(",0); put("+",2); put("-",2); put("*",3); put("/",3); put(")",7); put("=",20); } }; //不带xml参数的计算 public static String Calc(String expression) throws MyException { //判断表达式是否为空 if(expression==null||expression.equals("")) { throw new IllegalArgumentException("表达式不能为空!"); } Matcher matcher = EXPRESSION_PATTERN.matcher(expression); if(!matcher.matches()){ throw new IllegalArgumentException("表达式含有非法字符!"); } expression = formatExpression(expression); isExpression(expression); Stack<String> optstack = new Stack<>(); Stack<BigDecimal> numStack = new Stack<>(); StringBuilder numBuilder = new StringBuilder(16); char pre; for(int i=0;i<expression.length();i++) { char ch = expression.charAt(i); if(ch!=' ') { pre = ch; if((ch>='0'&&ch<='9')||ch=='.') { numBuilder.append(ch); }else { if(numBuilder.length()>0) { if(isNum(numBuilder.toString())==false) { throw new MyException("表达式格式错误!————数字格式错误(错误数字:'"+numBuilder+"'"); } numStack.push(new BigDecimal(numBuilder.toString())); numBuilder.delete(0, numBuilder.length()); } String operation = String.valueOf(ch); if(optstack.empty()) { optstack.push(operation); }else { if(operation.equals("(")) { optstack.push(operation); }else if(operation.equals(")")) { directCal(optstack, numStack,true); }else if(operation.equals("=")) { directCal(optstack, numStack,false); return numStack.pop().toString(); }else { compareOpt_Cal(numStack, optstack, operation); } } } } } if(numBuilder.length()>0) { numStack.push(new BigDecimal(numBuilder.toString())); } directCal(optstack, numStack, false); return numStack.pop().toString(); } //带xml参数的计算 public static String Calc(String expression,String xml) throws MyException { //判断表达式是否为空 if(expression==null||expression.equals("")) { throw new IllegalArgumentException("表达式不能为空!"); } Matcher matcher = EXPRESSION_PATTERN.matcher(expression); if(!matcher.matches()){ throw new IllegalArgumentException("表达式含有非法字符!"); } expression = formatExpression(expression); isExpression(expression); Option option=JaxbUtil.convertToJavaBean(xml, Option.class); int op_num = 0; Stack<String> optstack = new Stack<>(); Stack<BigDecimal> numStack = new Stack<>(); StringBuilder numBuilder = new StringBuilder(16); for(int i=0;i<expression.length();i++) { char ch = expression.charAt(i); if(ch!=' ') { if((ch>='0'&&ch<='9')||ch=='.') { numBuilder.append(ch); }else { if(++op_num>option.getOperation_num()) throw new MyException("操作符个数超过设置最大个数!"); if(numBuilder.length()>0) { BigDecimal value = new BigDecimal(numBuilder.toString()); if(value.doubleValue()>option.getMax()||value.doubleValue()<option.getMin()) throw new MyException("数据超出设置范围!"); if(isNum(numBuilder.toString())==false) { throw new MyException("表达式格式错误!————数字格式错误(错误数字:'"+numBuilder+"'"); } numStack.push(value); numBuilder.delete(0, numBuilder.length()); } String operation = String.valueOf(ch); if(optstack.empty()) { optstack.push(operation); }else { if(operation.equals("(")) { optstack.push(operation); }else if(operation.equals(")")) { directCal(optstack, numStack,true); }else if(operation.equals("=")) { directCal(optstack, numStack,false); return String.format("%."+option.getPoint_long()+"f", numStack.pop()); }else { compareOpt_Cal(numStack, optstack, operation); } } } } } if(numBuilder.length()>0) { numStack.push(new BigDecimal(numBuilder.toString())); } directCal(optstack, numStack, false); return String.format("%."+option.getPoint_long()+"f", numStack.pop()); } private static void compareOpt_Cal(Stack<BigDecimal> numstack,Stack<String> optstack,String operation) throws MyException { String topOpt = optstack.peek(); int comp_val = getPriority(topOpt, operation); if(comp_val==-1||comp_val==0) { String opt = optstack.pop(); BigDecimal num2 = numstack.pop(); BigDecimal num1 = numstack.pop(); BigDecimal result = calDouble(opt, num1, num2); numstack.push(result); if(optstack.empty()) { optstack.push(operation); }else { compareOpt_Cal(numstack, optstack, operation); } }else { optstack.push(operation); } } //判断两个操作符的优先级 private static int getPriority(String op1,String op2) { return OP_PRIORITY_MAP.get(op2)-OP_PRIORITY_MAP.get(op1); } //两个数之间的运算,注意除数不能为0 private static BigDecimal calDouble(String operation,BigDecimal num1,BigDecimal num2) throws MyException { BigDecimal result = new BigDecimal(0); switch (operation) { case "+": result = num1.add(num2); break; case "-": result = num1.subtract(num2); break; case "*": result = num1.multiply(num2); break; case "/": if(num2.equals(BigDecimal.ZERO)) { throw new MyException("表达式格式错误!————数字格式错误(除数不能为0:'"+num1+"/"+num2+"')"); } result = num1.divide(num2,10,BigDecimal.ROUND_DOWN); break; default: break; } return result; } //递归计算 private static void directCal(Stack<String> opStack,Stack<BigDecimal> numStack,boolean haved) throws MyException { String opt = opStack.pop(); BigDecimal num2 = numStack.pop(); BigDecimal num1 = numStack.pop(); BigDecimal result = calDouble(opt, num1, num2); numStack.push(result); if(haved) { if("(".equals(opStack.peek())) { opStack.pop(); }else { directCal(opStack, numStack,haved); } }else { if(!opStack.empty()) { directCal(opStack, numStack, haved); } } } //判断表达式的合法性(字符合法性) public static void isExpression(String expression) throws MyException { char pre=' ',cur=' '; int l_bracket_num=0,r_bracket_num=0; for(int i=0;i<expression.length();i++) { cur=expression.charAt(i); if(cur=='(') { l_bracket_num++; }else if(cur==')') { r_bracket_num++; } if(i>0) { if(pre=='.'&&(cur=='.'||cur=='('||cur==')'||cur=='+'||cur=='-'||cur=='*'||cur=='/')) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if((pre=='.'||pre=='('||pre==')'||pre=='+'||pre=='-'||pre=='*'||pre=='/')&&cur=='.') { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if((cur=='.'||cur==')'||cur=='+'||cur=='-'||cur=='*'||cur=='/')&&pre=='(') { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if((pre=='.'||pre=='('||pre=='+'||pre=='-'||pre=='*'||pre=='/')&&cur==')') { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if((pre=='+'||pre=='-'||pre=='*'||pre=='/')&&(cur=='+'||cur=='-'||cur=='*'||cur=='/')) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if(cur=='='&&i!=expression.length()-1) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if(cur=='='&&(pre=='+'||pre=='-'||pre=='*'||pre=='/'||pre=='(')) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if(cur=='('&&(pre>='0'&&pre<='9')) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); }else if(pre==')'&&(cur>='0'&&cur<='9')) { throw new MyException("表达式格式错误!————操作符格式错误(错误字符区域:'"+pre+cur+"')"); } }else { if(cur=='/'||cur=='*'||cur=='.'||cur==')'||cur=='=') throw new MyException("表达式格式错误!————表达式首字符不符合规范(错误字符:'"+cur+"'"); } pre=cur; } if(l_bracket_num!=r_bracket_num) throw new MyException("表达式格式不正确!————存在不匹配的左右括号"); } //判断表达式中数字的合法性 public static boolean isNum(String num) { if(num.contains(".")) { for(int i=0;i<num.indexOf('.');i++){ if(i==0&&num.charAt(0)=='0'&&num.indexOf('.')>1) { return false; } } }else { if(num.charAt(0)=='0'&&num.length()>1) return false; } return true; } //判断表达式的开头是否为+或-,如果是,则在其前面加上0方便操作 public static String formatExpression(String expression) { String result=""; if(expression.charAt(0)=='+'||expression.charAt(0)=='-') expression = "0"+expression; result = expression.replaceAll("[(]-", "(0-"); result = result.replaceAll("[(][+]", "(0+"); return result; } public static void main(String[] args) throws MyException { Option option = new Option(); //设置最大字符数 option.setOperation_num(10); //设置数值范围的最小值 option.setMin(-1000); //设置数值范围的最大值 option.setMax(1000); //设置结果保留的小数位 option.setPoint_long(2); String xml = JaxbUtil.convertTomXml(option); //传入带xml参数的计算方法(如不需要直接去掉该参数即可) System.out.println(Calc("12+87",xml)); } }
最后就是一个bean
package com.core.bean; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Option { private int operation_num; private double min; private double max; private int point_long; public int getOperation_num() { return operation_num; } public void setOperation_num(int operation_num) { this.operation_num = operation_num; } public double getMin() { return min; } public void setMin(double min) { this.min = min; } public double getMax() { return max; } public void setMax(double max) { this.max = max; } public int getPoint_long() { return point_long; } public void setPoint_long(int point_long) { this.point_long = point_long; } }