Java中的布尔表达式求值

13

我正在寻找一种相对简单的方法(与编写解析器相比)来在Java中评估布尔表达式,并且我不想使用JEP库。

我有一个字符串表达式,例如:(x > 4 || x < 8 && p > 6),我的目标是用实际值替换变量。

是否有一种方法可以评估这个表达式?需要注意的是,这可以是任意深度嵌套的表达式,因此编写解析器会非常复杂。

10个回答

16

1
这是一个很好的例子,展示了它的使用方法。http://commons.apache.org/jexl/reference/examples.html - blak3r

7

使用jexl(http://commons.apache.org/jexl/),您可以像这样完成此操作

    JexlEngine jexl = new JexlEngine();
    jexl.setSilent(true);
    jexl.setLenient(true);

    Expression expression = jexl.createExpression("(a || b && (c && d))");
    JexlContext jexlContext = new MapContext();

    //b and c and d should pass
    jexlContext.set("b",true);
    jexlContext.set("c",true);
    jexlContext.set("d",true);

    assertTrue((Boolean)expression.evaluate(jexlContext));

    jexlContext = new MapContext();

    //b and c and NOT d should be false
    jexlContext.set("b",true);
    jexlContext.set("c",true);

    //note this works without setting d to false on the context
    //because null evaluates to false

    assertFalse((Boolean)expression.evaluate(jexlContext));

我在使用jexl时遇到的一个问题是它的优先级。我有一个情况,需要在评估&&之前评估||。因此,上述表达式变成了(a || b) && (c && d)。在jexl中,仅使用'a'的上下文将评估为true。 - Joseph
仅供参考:我尝试了您的表达式(a||b)&&(c&&d)的示例,看起来已经修复了。只有'a'的值为'false',这是正确的。 - membersound

6
你可以使用Java6中的脚本引擎,选择任何流行的脚本语言,如Scala, Ruby, Python, GroovyJavascript。然后,您只需要确保要评估的表达式使用正确的语言编写。Groovy可能是最容易且集成最好的选项。
我已经成功使用此方法实现了一个功能,提供了类似于流行电子表格应用程序中的公式/计算列的功能。

1

0
你可以尝试使用这个库https://github.com/Shy-Ta/expression-evaluator-demo - 里面的说明文档有很多例子。该库使用Java和Groovy。
除了支持这种用例外,它还支持许多其他类似Excel的函数。而且,像示例中演示的那样添加新函数非常简单。
      ExpressionsEvaluator evalExpr = ExpressionsFactory.create("(x > 4 || x < 8 && p > 6)");  
      Map<String, Object> variables = new HashMap<String, Object>();  
      variables.put("x", 100);  
      variables.put("p", 10);
      evalExpr.eval();

0

这个链接似乎在写作时并没有起作用。此外,这个库是否支持比较运算符和像OP所问的布尔值? - andr

0
尝试使用Janino http://docs.codehaus.org/display/JANINO/Home 它非常简单易用,例如(摘自http://docs.codehaus.org/display/JANINO/Basic):
// Compile the expression once; relatively slow.
ExpressionEvaluator ee = new ExpressionEvaluator(
    "c > d ? c : d",                     // expression
    int.class,                           // expressionType
    new String[] { "c", "d" },           // parameterNames
    new Class[] { int.class, int.class } // parameterTypes
);

// Evaluate it with varying parameter values; very fast.
Integer res = (Integer) ee.evaluate(
    new Object[] {          // parameterValues
        new Integer(10),
        new Integer(11),
    }
);
System.out.println("res = " + res);

0

JUEL 提供了 Java 统一表达式语言的实现,而不需要显式地绑定到 JSP。这里是它的快速入门指南,其中表达式求值(该页面上的#3)是您感兴趣的部分。

另外,Spring 3.0 提供了自己的(虽然有些相似)表达式语言。不过,只有在您已经使用 Spring 的情况下才有意义选择此选项 - 我不会仅为 EL 引入它。


0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接