结对开发

本次结对开发主要是要开发一个可以用于四则运算调用的接口

实现功能: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());
    }
}
View Code

计算功能:

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;
    }
    
}
View Code
原文地址:https://www.cnblogs.com/ljpljm/p/13082262.html