2009-11-15 18 views
10

Sto cercando un modo relativamente più semplice (rispetto alla scrittura di un parser) per valutare espressioni booleane in Java e non voglio utilizzare la libreria JEP.Valutazione espressione booleana in Java

Ho un'espressione String come: (x > 4 || x < 8 && p > 6) e il mio obiettivo è sostituire le variabili con i valori.

C'è un modo in cui posso valutare questa espressione?

Tenere presente che questo può essere di qualsiasi livello profondo, quindi scrivere un parser sarebbe molto complesso.

risposta

6

è possibile utilizzare il motore di scripting in Java6 e scegliere una qualsiasi delle diffusi linguaggi di scripting come Scala, Ruby, Python, Groovy e Javascript. Tutto quello che devi fare è assicurarti che l'espressione che vuoi valutare sia nella lingua giusta. Groovy è probabilmente il più semplice e si integrerà meglio.

Ho usato questo metodo con successo per una funzione che offre funzionalità molto simili a una formula/colonna calcolata in un foglio di calcolo popolare.

0

JUEL fornisce un'implementazione di Unified Expression Language di Java senza essere esplicitamente associato a JSP. Ecco la sua Quick Start guide, valutazione delle espressioni (# 3 in quella pagina) è la parte che ti interessa.

In alternativa, Spring 3.0 fornisce il proprio (anche se in qualche modo simile) linguaggio delle espressioni. Questa opzione ha senso solo se stai già usando Spring, però - non lo farei solo per EL.

14

Utilizzare Apache Commons Jexl; che è esattamente progettato per tale requisito.

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

+1

+1 Ecco un buon esempio di come viene utilizzato. http://commons.apache.org/jexl/reference/examples.html – blak3r

0

V'è un'API disponibile presso http://lts.online.fr/dev/java/math.evaluator/

Esempio:

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

Questo collegamento non sembra funzionare, almeno al momento della scrittura. Inoltre, questa libreria supporta operatori di confronto e valori 'booleani 'come richiesto dall'OP? – andr

7

Utilizzando jexl (http://commons.apache.org/jexl/), è possibile ottenere questo risultato come questo

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

L'unico problema che avevo con jexl era la sua priorità. Ho un caso in cui ho bisogno di valutare || prima di valutare &&. Quindi l'espressione sopra diventa (a || b) && (c && d). In jexl, l'uso di un contesto di "a" equivale a true. – Joseph

+0

Solo per riferimento: ho provato l'esempio con la tua espressione di '(a || b) && (c && d)' e sembra risolto. Solo 'a' restituisce 'falso', che è corretto. – membersound

0

Si potrebbe provare questa libreria https://github.com/Shy-Ta/expression-evaluator-demo - il read me ha un discreto numero di esempi. La libreria utilizza java e groovy.

Oltre a supportare questo caso d'uso, supporta anche molte altre funzioni simili a Excel. Inoltre, è molto semplice aggiungere nuove funzioni come mostrato nell'esempio.

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