(JAVA)String类型的逻辑语句编译

项目中遇到了动态配置条件触发相应事件的需求,需要根据String类型的逻辑语句,以及动态获取的数据,计算数据对应的结果,java实现。解决思路及代码实现如下,有需要的同学请自取。一、需求提取根据需求,抛开业务部分,我们可以将需求简化成以下核心逻辑。输入String类型的逻辑字符串,支持的逻辑符号包括>,<,<=,>=,==,()。例如:"(a>1&&b...

(JAVA)String类型的逻辑语句编译

  项目中遇到了动态配置条件触发相应事件的需求,需要根据String类型的逻辑语句,以及动态获取的数据,计算数据对应的结果,java实现。解决思路及代码实现如下,有需要的同学请自取。


一、需求提取

  根据需求,抛开业务部分,我们可以将需求简化成以下核心逻辑。输入String类型的逻辑字符串,支持的逻辑符号包括 > , < , <= ,>= ,== ,() 。 例如: "(a>1&&b<2)||(c>=3&&d==4)" ,动态解析该字符串,并对输入的任意json类数据做出正确的逻辑判断。如{“b” : 10 , "a" : 9 , "c":"error" }。

二、设计思路

  因为每一个最小的逻辑点。如 “a>1” 都只有两个结果:成功或者失败,并且成功或者失败后,往往需要执行下一个逻辑,所以该逻辑模型可以转换成一个二叉树的结构。据此我们先画出"(a>1&&b<2)||(c>=3&&d==4)" 的逻辑图

  每一个逻辑根据成功或者失败,指向了另外的逻辑,或者指向了最终结果,这里我们可以把指向的这个操作等价成指针,该指针指向了另外一个逻辑实体,或者指向了最终结果,又因为java中的指针,或者说引用都是需要事先指定数据类型的,如果我们使用逻辑实体和布尔类型的两种数据对象,那我们就只能将引用声明为两种数据对象的统一父类Object。但是因为Object在使用过程中涉及到了类型的判断及转化,很不方便,所以我们直接使用逻辑实体表示 逻辑,用 null表示可以直接返回最终结果。

  除了两个引用以外,该逻辑实体应该还包括三个关键字,三个关键字有数据对应的key值"a" , 数据对应的逻辑符号 “>”,数据对应的阈值"1"。

  据此,我们可以确定该逻辑实体的五个字段 ,建出以下实体

 1 public class Logic { 2  //值对应的key值 3  private String key; 4  //逻辑符号 包括 > < >= <=  == 5  private double symbol; 6  //阈值 7  private double value; 8  //成功是返回,为null时表示最终结果为true 9  private Logic sucLogic;10  //失败是返回,为null时表示最终结果为false 11  private Logic failLogic; 12 }

  使用该实体的原因如下:

  1) 可以很清楚的表明逻辑关系

  2) 增加了处理时的开销,减少了使用时的开销,更好的支持大批量的数据判断

三、编码实现

  1. 根据string生成Logic对象的代码

  1 public class CreateLogic {  2   3  private static String[] symbol = {">=","<=",">","<","=="};  4  private static String[] backSymbol = {"<=",">=","<",">","=="};  5   6  public static void main(String[] args) {  7CreateLogic createLogic = new CreateLogic();  8Logic logic = createLogic.handleContentLogic("(a>1&&b<2)||(c>=3&&d==4)");  9   System.out.println( logic); 10  } 11  12  private Logic handleContentLogic(String content) { 13//1.去除掉首位的无效括号 14content = this.removeNoUseContent( content ); 15//2.将content拆成小的逻辑块。 16List<String> blockContents = new ArrayList<>(); 17int point = 0; 18int flag = 0; 19for (int i = 0; i < content.length(); i  ) { 20 char c = content.charAt(i); 21 if( '(' ==  c){ 22  flag  ; 23  continue; 24 }else if( ')' == c){ 25  flag--; 26  if( flag == 0 ){ 27blockContents.add( content.substring( point , i1) ); 28point = i1; 29  } 30 }else if( flag == 0 && ('|' == content.charAt(i) || '&' == content.charAt(i)) ){ 31  if( i - point > 1){ 32   blockContents.add( content.substring( point , i ) ); 33point = i; 34  } 35 }else if( i == content.length() - 1){ 36  blockContents.add( content.substring( point , i1 ) ); 37 } 38   } 39//3.遍历获取最终逻辑 40Logic logic = null; 41for (int i = 0; i < blockContents.size(); i  ) { 42 String blockContent = blockContents.get(i); 43 if( blockContent.startsWith("||(") ){ 44  Logic logic1 = this.handleContentLogic(blockContent.substring(2)); 45  logic.setFailLogicEveryFail(logic1); 46 }else if( blockContent.startsWith("&&(") ){ 47  Logic logic1 = this.handleContentLogic(blockContent.substring(2)); 48  logic.setSucLogicEveryFail(logic1); 49 }else if( blockContent.startsWith("&&") ) { 50  Logic logic1 = this.getLogicBySimpleContent(blockContent.substring(2)); 51  logic1.setSucLogicEveryFail(logic); 52  logic = logic1; 53 }else if( blockContent.startsWith("||") ) { 54  Logic logic1 = this.getLogicBySimpleContent(blockContent.substring(2)); 55  logic1.setFailLogicEveryFail(logic); 56  logic = logic1; 57 }else { 58  logic = this.getLogicBySimpleContent(blockContent); 59 } 60   } 61return logic; 62  } 63  64  /** 65   * 去除掉首位的无效括号 66   * @param content 67   * @return 68*/ 69  public String removeNoUseContent( String content ){ 70List<String> list = new ArrayList<>(Arrays.asList(content.split(""))) ; 71//1.首位的小括号为无效的小括号,先去除掉 72int flag1 = 0; 7
源文地址:https://www.guoxiongfei.cn/cntech/17047.html