2009-11-15 18 views
10

Je suis à la recherche d'un moyen relativement plus simple (par rapport à l'écriture d'un analyseur) d'évaluer les expressions booléennes en Java, et je ne veux pas utiliser la bibliothèque JEP.Évaluation d'expression booléenne en Java

J'ai une expression String comme: (x > 4 || x < 8 && p > 6) et mon but est de remplacer les variables par des valeurs.

Existe-t-il un moyen par lequel je peux évaluer cette expression? Gardez à l'esprit que cela peut être de n'importe quel niveau, donc écrire un analyseur serait très complexe.

Répondre

6

Vous pouvez utiliser le moteur de script dans Java6 et choisir l'une des langages de script populaires comme Scala, Ruby, Python, Groovy et Javascript. Tout ce que vous avez à faire est de vous assurer que l'expression que vous voulez évaluer est dans la bonne langue. Groovy est probablement le plus facile et s'intégrera le mieux.

J'ai utilisé cette méthode avec succès pour une fonction offrant des fonctionnalités similaires à une formule/colonne calculée dans une application de feuille de calcul populaire.

0

JUEL fournit une implémentation du langage d'expression unifiée Java sans être explicitement lié à JSP. Voilà son Quick Start guide, l'évaluation de l'expression (# 3 sur cette page) est la partie qui vous intéresse.

Sinon, Spring 3.0 fournit son propre (quoique un peu similaire) langue d'expression. Cette option n'a de sens que si vous utilisez déjà Spring, je ne voudrais pas l'utiliser uniquement pour EL.

14

Utiliser Apache Commons Jexl; qui est exactement conçu pour une telle exigence.

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

+1

+1 Voici un bon exemple de la façon dont il est utilisé. http://commons.apache.org/jexl/reference/examples.html – blak3r

0

Il y a une API disponible à http://lts.online.fr/dev/java/math.evaluator/

Exemple:

MathEvaluator m = new MathEvaluator("-5-6/(-2) + sqr(15+x)"); 
m.addVariable("x", 15.1d); 
System.out.println(m.getValue()); 
+0

Ce lien ne semble pas fonctionner, du moins au moment de l'écriture. Aussi, cette bibliothèque supporte-t-elle les opérateurs de comparaison et les valeurs 'boolean' comme demandé par le PO? – andr

7

En utilisant jexl (http://commons.apache.org/jexl/), vous pouvez y arriver comme ça

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)); 
+0

Le seul problème que j'avais avec jexl était sa hiérarchisation. J'ai un cas où j'ai besoin d'évaluer || avant d'évaluer &&. Donc l'expression ci-dessus se transforme en (a || b) && (c && d). Dans jexl, l'utilisation d'un contexte de juste 'a' donnerait une évaluation vraie. – Joseph

+0

Juste pour référence: j'ai essayé l'exemple avec votre expression de '(a || b) && (c && d)' et il semble fixe. Juste 'a' évalue à 'faux', ce qui est correct. – membersound

0

Vous pouvez essayer cette bibliothèque https://github.com/Shy-Ta/expression-evaluator-demo - la lecture a un bon nombre d'exemples. La bibliothèque utilise Java et groovy.

En plus de prendre en charge ce cas d'utilisation, il prend également en charge de nombreuses autres fonctions similaires. En outre, il est très simple d'ajouter de nouvelles fonctions comme démontré dans l'exemple.

 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();