2009-11-15 7 views
10

Я ищу относительно простой (по сравнению с написанием парсера) способ оценки булевых выражений в Java, и я не хочу использовать библиотеку JEP.Оценка булевых выражений в Java

У меня есть выражение в виде строки: (x > 4 || x < 8 && p > 6), и моя цель - заменить переменные значениями.

Есть ли способ, с помощью которого я могу оценить это выражение?

Имейте в виду, что это может быть любой уровень глубины, поэтому написать парсер будет очень сложным.

ответ

6

Вы можете использовать скриптовый движок в Java6 и выбрать любой из популярных скриптовых языков, как Scala, Ruby, Python, Groovy и Javascript. Чем все, что вам нужно сделать, это убедиться, что выражение, которое вы хотите оценить, находится на правильном языке. Groovy, вероятно, самый простой и будет лучше интегрироваться.

Я успешно использовал этот метод для функций, предлагающих функции, похожие на формулу/вычисленный столбец в популярном приложении электронных таблиц.

0

JUEL обеспечивает реализацию Java Unified Expression Language без явной привязки к JSP. Вот его Quick Start guide, оценка выражения (№ 3 на этой странице) является интересующей вас частью.

В качестве альтернативы Spring 3.0 предоставляет свой собственный (хотя и несколько похожий) язык выражений. Этот вариант имеет смысл только в том случае, если вы уже используете Spring, но я бы не потянул его только за EL.

14

Использование Apache Commons Jexl; который точно предназначен для такого требования.

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

+1

+1 Вот хороший пример того, как он используется. http://commons.apache.org/jexl/reference/examples.html – blak3r

0

Существует API доступен на http://lts.online.fr/dev/java/math.evaluator/

Пример:

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

Эта ссылка, похоже, не работает, по крайней мере, на момент написания. Кроме того, поддерживает ли эта библиотека операторы сравнения и значения 'boolean', такие как OP? – andr

0

Я нашел библиотеки, перечисленные здесь слишком сложными для моих нужд.Я закончил с использованием Fscript: http://fscript.sourceforge.net/

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

Единственный вопрос, который я имел с jexl, - это его приоритетность. У меня есть случай, когда мне нужно оценить || прежде чем я оцениваю &&. Таким образом, указанное выражение превращается в (a || b) && (c && d). В jexl использование контекста только «a» будет оцениваться как true. – Joseph

+0

Только для справки: я попробовал пример с выражением '(a || b) && (c && d)', и он кажется исправленным. Просто «а» оценивает «ложь», что является правильным. – membersound

0

Вы можете попробовать эту библиотеку https://github.com/Shy-Ta/expression-evaluator-demo - у меня есть много примеров. Библиотека использует java и groovy.

В дополнение к поддержке этого прецедента, он также поддерживает множество других превосходных функций. Кроме того, очень просто добавить новые функции, как показано в примере.

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

 Смежные вопросы

  • Нет связанных вопросов^_^