12

I'm looking for a relatively simpler (when compared with writing a parser) way to evaluate boolean expressions in Java, and I do not want to use the JEP library.

I have a String expression like: (x > 4 || x < 8 && p > 6) and my aim is to replace the variables with values.

Is there a way by which I can evaluate this expression?

Bear in mind that this can be any level deep so writing a parser would be very complex.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
TJ-
  • 14,085
  • 12
  • 59
  • 90

10 Answers10

16

Use Apache Commons Jexl; which is exactly designed for such requirement.

http://commons.apache.org/jexl/

Venkat Sadasivam
  • 1,435
  • 5
  • 24
  • 42
  • 1
    +1 Here's a good example of how it's used. http://commons.apache.org/jexl/reference/examples.html – blak3r Jun 17 '10 at 17:05
7

Using jexl (http://commons.apache.org/jexl/), you can accomplish this like this

    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));
Robert
  • 39,162
  • 17
  • 99
  • 152
Matthew Kirkley
  • 4,138
  • 5
  • 31
  • 33
  • The one issue I had with jexl was its prioritization. I have a case where I need to evaluate || before I evaluate &&. So the above expression turns into (a||b)&&(c&&d). In jexl, using a context of just 'a' would evaluate to true. – Joseph Dec 13 '12 at 19:02
  • Just for reference: I tried the example with your expression of `(a||b)&&(c&&d)` and it seems fixed. Just 'a' evaluates to 'false', which is correct. – membersound Jan 17 '13 at 15:26
6

You could use the scripting engine in Java6 and the choose any of the popular scripting languages like Scala, Ruby, Python, Groovy, and Javascript. Than all you have to do is make sure the expression you want to evaluate is in the right language. Groovy is probably the easiest and will integrate best.

I have used this method successfully for a feature offering capabilities much like a formula / calculated column in a popular spreadsheet application.

DylanYi
  • 196
  • 1
  • 10
basszero
  • 29,624
  • 9
  • 57
  • 79
1

Here is the latest resources for expression evaluation framework

The information page is at http://expressionoasis.vedantatree.com/

Kaouni
  • 11
  • 1
0

JUEL provides an implementation of Java's Unified Expression Language without being explicitly tied to JSP. Here's its Quick Start guide, expression evaluation (#3 on that page) is the part you're interested in.

Alternatively, Spring 3.0 provides its own (though somewhat similar) expression language. This option only makes sense if you're already using Spring, though - I wouldn't pull it in just for EL.

ChssPly76
  • 99,456
  • 24
  • 206
  • 195
0

try Janino http://docs.codehaus.org/display/JANINO/Home It is very simple to use eg (taken from 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);
Devashish Mamgain
  • 2,077
  • 1
  • 18
  • 39
0

There is a API available at http://lts.online.fr/dev/java/math.evaluator/

Example:

MathEvaluator m = new MathEvaluator("-5-6/(-2) + sqr(15+x)");
m.addVariable("x", 15.1d);
System.out.println( m.getValue() );
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
Azeem
  • 1
  • This link does not seem to be working, at least at the time of writing. Also, does this library support comparison operators and `boolean` values like the OP asked? – andr Dec 31 '12 at 11:18
0

Try http://code.google.com/p/xpressionengine/ for open source implementation

Mohit
  • 1
0

You could try this library https://github.com/Shy-Ta/expression-evaluator-demo - the read me has a fair number of examples. The library uses java and groovy.

In addition to supporting this use case, it also supports a lot of other excel like functions. Also, it is very simple to add new functions as demonstrated in the example.

      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();
Scorpion
  • 3,938
  • 24
  • 37
0

I found the libraries listed here too complicated for my needs. I ended up using Fscript: http://fscript.sourceforge.net/

NateS
  • 5,751
  • 4
  • 49
  • 59