You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中动态评估AND、OR、NOT逻辑运算的实现方案

扩展支持NOT操作的动态表达式解析实现

核心思路

  1. 词层扩展:在原有词法规则中加入NOT关键字识别,明确它是优先级高于AND/OR的单目运算符。
  2. 语法规则调整:重构表达式解析的层级逻辑,让NOT可以作用于单个条件或括号包裹的子表达式,语法结构如下:
    expression → term (OR term)*
    term → factor (AND factor)*
    factor → NOT factor | condition | (expression)
    condition → identifier (EQ | IN) value
    
  3. 表达式节点扩展:新增NotExpression类,实现表达式求值接口,核心逻辑是对内部表达式的结果取反。

代码实现示例

假设已基于Tagir Valeev的方案实现了AND/OR及基础条件的解析,以下是扩展NOT操作的完整代码:

1. 表达式核心接口与实现类

import java.util.Map;
import java.util.List;

// 基础表达式求值接口
interface Expression {
    boolean evaluate(Map<String, Object> data);
}

// NOT表达式实现:对内部表达式结果取反
class NotExpression implements Expression {
    private final Expression innerExpr;

    public NotExpression(Expression innerExpr) {
        this.innerExpr = innerExpr;
    }

    @Override
    public boolean evaluate(Map<String, Object> data) {
        return !innerExpr.evaluate(data);
    }
}

// 基础条件表达式(如EmployeeShift='General')
class ConditionExpression implements Expression {
    private final String field;
    private final Operator operator;
    private final Object value;

    public ConditionExpression(String field, Operator operator, Object value) {
        this.field = field;
        this.operator = operator;
        this.value = value;
    }

    @Override
    public boolean evaluate(Map<String, Object> data) {
        Object actualValue = data.get(field);
        if (actualValue == null) return false;

        return switch (operator) {
            case EQ -> actualValue.equals(value);
            case IN -> ((List<?>) value).contains(actualValue);
        };
    }

    enum Operator {EQ, IN}
}

// 原有AND/OR表达式保持不变
class AndExpression implements Expression {
    private final Expression left;
    private final Expression right;

    public AndExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public boolean evaluate(Map<String, Object> data) {
        return left.evaluate(data) && right.evaluate(data);
    }
}

class OrExpression implements Expression {
    private final Expression left;
    private final Expression right;

    public OrExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public boolean evaluate(Map<String, Object> data) {
        return left.evaluate(data) || right.evaluate(data);
    }
}

2. 扩展后的递归下降解析器

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class ExpressionParser {
    private final List<Token> tokens;
    private int pos;

    public ExpressionParser(String exprStr) {
        this.tokens = tokenize(exprStr);
        this.pos = 0;
    }

    // 词法分析:将表达式拆分为Token
    private List<Token> tokenize(String expr) {
        List<Token> tokens = new ArrayList<>();
        // 匹配关键字、运算符、标识符、字符串值、括号
        Pattern pattern = Pattern.compile("(AND|OR|NOT|\\(|\\)|=|IN|'[^']+'|[a-zA-Z_][a-zA-Z0-9_]*)");
        Matcher matcher = pattern.matcher(expr.replaceAll("\\s+", ""));
        
        while (matcher.find()) {
            String value = matcher.group();
            if (value.equals("AND")) tokens.add(new Token(TokenType.AND, value));
            else if (value.equals("OR")) tokens.add(new Token(TokenType.OR, value));
            else if (value.equals("NOT")) tokens.add(new Token(TokenType.NOT, value));
            else if (value.equals("(")) tokens.add(new Token(TokenType.LPAREN, value));
            else if (value.equals(")")) tokens.add(new Token(TokenType.RPAREN, value));
            else if (value.equals("=")) tokens.add(new Token(TokenType.EQ, value));
            else if (value.equals("IN")) tokens.add(new Token(TokenType.IN, value));
            else if (value.startsWith("'") && value.endsWith("'")) tokens.add(new Token(TokenType.VALUE, value.substring(1, value.length()-1)));
            else tokens.add(new Token(TokenType.IDENTIFIER, value));
        }
        return tokens;
    }

    // 解析入口:处理OR连接的表达式
    public Expression parse() {
        return parseExpression();
    }

    private Expression parseExpression() {
        Expression expr = parseTerm();
        while (pos < tokens.size() && tokens.get(pos).type == TokenType.OR) {
            pos++;
            expr = new OrExpression(expr, parseTerm());
        }
        return expr;
    }

    // 处理AND连接的表达式
    private Expression parseTerm() {
        Expression expr = parseFactor();
        while (pos < tokens.size() && tokens.get(pos).type == TokenType.AND) {
            pos++;
            expr = new AndExpression(expr, parseFactor());
        }
        return expr;
    }

    // 处理NOT、括号表达式或基础条件(优先级最高)
    private Expression parseFactor() {
        if (pos >= tokens.size()) throw new IllegalArgumentException("表达式格式错误");
        
        Token token = tokens.get(pos);
        if (token.type == TokenType.NOT) {
            pos++;
            // 递归解析NOT后的因子,支持嵌套NOT(如NOT NOT(...))
            Expression inner = parseFactor();
            return new NotExpression(inner);
        } else if (token.type == TokenType.LPAREN) {
            pos++;
            Expression expr = parseExpression();
            if (pos >= tokens.size() || tokens.get(pos).type != TokenType.RPAREN) {
                throw new IllegalArgumentException("括号不匹配");
            }
            pos++;
            return expr;
        } else {
            return parseCondition();
        }
    }

    // 解析基础条件语句
    private Expression parseCondition() {
        if (pos >= tokens.size() || tokens.get(pos).type != TokenType.IDENTIFIER) {
            throw new IllegalArgumentException("预期字段名");
        }
        String field = tokens.get(pos).value;
        pos++;

        if (pos >= tokens.size() || (tokens.get(pos).type != TokenType.EQ && tokens.get(pos).type != TokenType.IN)) {
            throw new IllegalArgumentException("预期运算符=或IN");
        }
        ConditionExpression.Operator operator = tokens.get(pos).type == TokenType.EQ ? ConditionExpression.Operator.EQ : ConditionExpression.Operator.IN;
        pos++;

        if (pos >= tokens.size() || tokens.get(pos).type != TokenType.VALUE) {
            throw new IllegalArgumentException("预期值");
        }
        Object value = tokens.get(pos).value;
        // 处理IN操作的多值(如'ADMIN,MANAGER'拆分为列表)
        if (operator == ConditionExpression.Operator.IN) {
            value = List.of(value.toString().split(","));
        }
        pos++;

        return new ConditionExpression(field, operator, value);
    }

    // Token定义
    private static class Token {
        enum TokenType {AND, OR, NOT, LPAREN, RPAREN, EQ, IN, IDENTIFIER, VALUE}
        final TokenType type;
        final String value;

        Token(TokenType type, String value) {
            this.type = type;
            this.value = value;
        }
    }
}

3. 使用示例

import java.util.Map;

public class ExpressionTest {
    public static void main(String[] args) {
        String exprStr = "EmployeeShift='General' AND NOT(EmployeeType='CONTRACT' OR Designation IN 'ADMIN')";
        ExpressionParser parser = new ExpressionParser(exprStr);
        Expression expr = parser.parse();

        // 测试数据1:满足条件
        Map<String, Object> data1 = Map.of(
                "EmployeeShift", "General",
                "EmployeeType", "FULLTIME",
                "Designation", "ENGINEER"
        );
        System.out.println(expr.evaluate(data1)); // 输出true

        // 测试数据2:不满足条件(EmployeeType为CONTRACT)
        Map<String, Object> data2 = Map.of(
                "EmployeeShift", "General",
                "EmployeeType", "CONTRACT",
                "Designation", "ENGINEER"
        );
        System.out.println(expr.evaluate(data2)); // 输出false
    }
}

关键说明

  • 优先级保障:通过递归下降的层级划分(expression→term→factor),确保NOT优先级最高,AND次之,OR最低,符合常规逻辑运算规则。
  • 扩展性:若需支持IN操作的多值列表(如Designation IN ('ADMIN','MANAGER')),可修改词法规则,识别括号包裹的多值集合。
  • 错误处理:示例包含基础的格式校验,实际使用可根据需求增强异常提示和边界场景处理。

内容的提问来源于stack exchange,提问作者User1512

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 07:35:41