啥都不说了直接上代码
public class TestSimpleExpression
{
public static void main(String[] str)
{
try
{
Map<String, Integer> map=new HashMap();
map.put("x", 4);
map.put("y", 5);
map.put("z", 7);
map.put("d", 2);

String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";
        str1 = str1.replaceAll("\\[\\[(.*?)\\]\\]","map.get(\"$1\")");

System.out.println(str1);
    
}
catch (Exception e)
{
System.out.println("Error: " + e);
}

}
}
一开始想的乐观了,以为这样替换之后应该能直接算出一个结果,结果只是进行了相应替换,有没有办法,替换之后直接可以进行计算……

解决方案 »

  1.   

    jdk6提供对脚本语言的支持,比如:javascript
    参考:ScriptEngine这个类的eval方法
      

  2.   

    这是js引擎的import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;public class TestSimpleExpression {
    public static void main(String[] str) {
    try {
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("var map=[];map[\"x\"]=");
    stringBuilder.append(4);
    stringBuilder.append(";map[\"y\"]=");
    stringBuilder.append(5);
    stringBuilder.append(";map[\"z\"]=");
    stringBuilder.append(7);
    stringBuilder.append(";map[\"d\"]=");
    stringBuilder.append(2);
    stringBuilder.append(";");
    String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]];";
    str1 = str1.replaceAll("\\[\\[(.*?)\\]\\]", "map[\"$1\"]");
    stringBuilder.append(str1); ScriptEngine javaScriptEngine = (new ScriptEngineManager()) .getEngineByExtension("js");
    System.out.println(javaScriptEngine.eval(stringBuilder.toString()));
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }
      

  3.   

    谢谢powerlee2008,jdk5下有办法吗?
      

  4.   


    try {
    Map<String, Integer> map = new HashMap();
    map.put("x", 4);
    map.put("y", 5);
    map.put("z", 7);
    map.put("d", 2); String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";
    str1 = str1.replaceAll("\\[\\[(.*?)\\]\\]", "map.get(\"$1\")");
    str1 =( map.get("x")+map.get("y")*map.get("z")/map.get("d")+map.get("x"))+"";
    System.out.println(str1); } catch (Exception e) {
    System.out.println("Error: " + e);
    }
      

  5.   

    谢谢longvs,这种方式不行,因为String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";是一个变量,我不知道这个表达式到底有多大
      

  6.   

    换一种方式问问,正则表达式有没有办法,把String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";
    换成map中对应元素的值,比如[[x]]换成map.get("x")的值即4,其他依次类推
      

  7.   

    jdk5可以下载以下jar包:commons-logging-1.1.1.jar、commons-jexl-2.0.1.jar、bsf-api-3.1.jar,加到classpath,然后就可以使用ScriptEngine了
      

  8.   

    JDK5滴:import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileOutputStream;public class TestSimpleExpression2 {
    private double x = 4;
    private double y = 5;
    private double z = 7;
    private double d = 2;

    private void compile() throws Throwable {
    String str1 = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";
    str1 = str1.replaceAll("\\[\\[(.*?)\\]\\]","map.get(\"$1\")");
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("import java.util.HashMap;");
    stringBuilder.append("import java.util.Map;");
    stringBuilder.append("public class TestSimle {");
    stringBuilder.append("private static Map<String, Double> map = new HashMap<String, Double>();");
    stringBuilder.append("public static double calculate() {");
    stringBuilder.append("map.put(\"x\",");
    stringBuilder.append(this.x);
    stringBuilder.append(");map.put(\"y\",");
    stringBuilder.append(this.y);
    stringBuilder.append(");map.put(\"z\",");
    stringBuilder.append(this.z);
    stringBuilder.append(");map.put(\"d\",");
    stringBuilder.append(this.d);
    stringBuilder.append(");return ");
    stringBuilder.append(str1);
    stringBuilder.append(";}}");
    DataOutputStream ostream = new DataOutputStream(new FileOutputStream("bin/TestSimle.java"));
    ostream.writeBytes(stringBuilder.toString());
    ostream.close();
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("cmd /c javac bin/TestSimle.java");
    process.waitFor();
    DataInputStream iStream = new DataInputStream(process.getInputStream());
    byte[] readBytes = new byte[1024];
    iStream.read(readBytes);
    String result = new String(readBytes);
    if (result.indexOf("Exception") >= 0) throw new Throwable(result);
    }

    public void calculate() throws Throwable {
    this.compile();
    System.out.println(Class.forName("TestSimle").getMethod("calculate").invoke(null, new Object[]{}));
    }

    public static void main(String[] args) throws Throwable {
    new TestSimpleExpression2().calculate();
    }
    }
      

  9.   


    str1 = str1.replaceAll("\\[\\[(.*?)\\]\\]", "map.get(\"$1\")");
    你这个替换,肯定只是完成了替换拉,并没有完成计算。但替换后不是得到了表达式了嘛,你再调用一下这个表达式,就是计算了。
      

  10.   


    powerlee2008,ticmy,谢谢你们,我现在在jdk1.5下使用了包commons-logging-1.1.1.jar、commons-jexl-2.0.1.jar、bsf-api-3.1.jar,但是debug发现在这句
    ScriptEngine javaScriptEngine = (new ScriptEngineManager()).getEngineByExtension("js");
    获得的javaScriptEngine 是 null,这个怎么解决啊
      

  11.   

    ScriptEngine javaScriptEngine = (new ScriptEngineManager()).getEngineByName("jexl");
      

  12.   

    使用 Janino 吧,到 http://docs.codehaus.org/display/JANINO/Download#Download-packages 去下载最新的 Janino 包。把 janino.jar, commons-compiler.jar 放到 classpath 下。测试代码如下:import java.lang.reflect.InvocationTargetException;
    import java.util.HashMap;
    import java.util.Map;import org.codehaus.commons.compiler.CompileException;
    import org.codehaus.janino.ExpressionEvaluator;public class JaninoTest {    public static void main(String[] args) throws CompileException, InvocationTargetException {
            Map<String, Integer> map = new HashMap<String, Integer>();
            map.put("x", 4);
            map.put("y", 5);
            map.put("z", 7);
            map.put("d", 2);        String str = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";        str = str.replace("[[", "").replace("]]", "");        System.out.println(eval(str, map, double.class));
        }    /**
         * 计算表达式
         *
         * @param <T>           返回类型
         * @param str           表达式
         * @param args          参数
         * @param returnType    返回类型
         * @return
         * 2011-5-13 下午05:02:06
         */
        @SuppressWarnings("unchecked")
        public static <T> T eval(String str, Map<String, ? extends Number> args, Class<T> returnType) {        String[] argNames = new String[args.size()];
            Number[] argValues = new Number[args.size()];
            Class<?>[] argTypes = new Class[args.size()];
            int k = 0;
            for(Map.Entry<String, ? extends Number> entry : args.entrySet()) {
                argNames[k] = entry.getKey();
                argValues[k] = entry.getValue();
                argTypes[k] = entry.getValue().getClass();
                k++;
            }        ExpressionEvaluator evaluator = new ExpressionEvaluator();
            evaluator.setExpressionType(returnType);
            evaluator.setParameters(argNames, argTypes);
            try {
                evaluator.cook(str);
                return (T)evaluator.evaluate(argValues);
            } catch (CompileException e) {
                e.printStackTrace();
                return null;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
      

  13.   

    改为这个后报
    Error: javax.script.ScriptException: org.apache.commons.jexl2.JexlException: org.apache.commons.jexl2.scripting.JexlScriptEngine.eval@214 parsing failed
      

  14.   

    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    public class Test {
    public static void main(String[] args) throws ScriptException {
    String exp = "[[x]]+[[y]]*[[z]]/[[d]]+[[x]]";
    exp = exp.replaceAll("\\[", "").replaceAll("\\]", "");
    System.out.println(exp);
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine scriptEngine = manager.getEngineByName("jexl");
    scriptEngine.put("x", 2);
    scriptEngine.put("y", 3);
    scriptEngine.put("z", 4);
    scriptEngine.put("d", 5);
    Object result = scriptEngine.eval(exp);
    System.out.println("结果:" + result + " ;类型:" + result.getClass().getName());
    }
    }