1. 程式人生 > >(JAVA)String型別的邏輯語句編譯

(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 
13     //後面會用到的兩個方法
14     //在logic樹的每一層失敗分支子樹上都加一個成功時呼叫的物件
15     public void setSucLogicEveryFail(Logic logic){
16         Logic logic1 = this;
17         while (true){
18             logic1.setSucLogic( logic );
19             if ( logic1.getFailLogic != null ){
20                 logic1 = logic1.getFailLogic();
21             }else {
22                 return;
23             }
24         }
25     }
26     //在logic樹的每一層成功分支上子樹上都加一個失敗時呼叫的物件
27     public void setFailLogicEverySuc(Logic logic){
28         Logic logic1 = this;
29         while (true){
30             logic1.setFailLogic( logic );
31             if ( logic1.getSucLogic != null ){
32                 logic1 = logic1.getSucLogic ();
33             }else {
34                 return;
35             }
36         }
37     } 
38 } 

 

  使用該實體的原因如下:

  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) {
  7         CreateLogic createLogic = new CreateLogic();
  8         Logic 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.去除掉首位的無效括號
 14         content = this.removeNoUseContent( content );
 15         //2.將content拆成小的邏輯塊。
 16         List<String> blockContents = new ArrayList<>();
 17         int point = 0;
 18         int flag = 0;
 19         for (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 ){
 27                     blockContents.add( content.substring( point , i + 1) );
 28                     point = i + 1;
 29                 }
 30             }else if( flag == 0 && ('|' == content.charAt(i) || '&' == content.charAt(i)) ){
 31                 if( i - point > 1){
 32                     blockContents.add( content.substring( point , i ) );
 33                     point = i;
 34                 }
 35             }else if( i == content.length() - 1){
 36                 blockContents.add( content.substring( point , i + 1 ) );
 37             }
 38         }
 39         //3.遍歷獲取最終邏輯
 40         Logic logic = null;
 41         for (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.setFailLogicEverySuc(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.setFailLogicEverySuc(logic);
 56                 logic = logic1;
 57             }else {
 58                 logic = this.getLogicBySimpleContent(blockContent);
 59             }
 60         }
 61         return logic;
 62     }
 63 
 64     /**
 65      * 去除掉首位的無效括號
 66      * @param content
 67      * @return
 68      */
 69     public String removeNoUseContent( String content ){
 70         List<String> list = new ArrayList<>(Arrays.asList(content.split(""))) ;
 71         //1.首位的小括號為無效的小括號,先去除掉
 72         int flag1 = 0;
 73         int flag2 = 0;
 74         while (true){
 75             if( "(".equals(list.get(0) )){
 76                 flag1++;
 77                 list.remove(0);
 78             }else {
 79                 break;
 80             }
 81         }
 82         if( flag1 > 0 ){
 83             for (int i = 0; i < list.size(); i++) {
 84                 if( flag1 == 0 ){
 85                     break;
 86                 }
 87                 if( "(".equals(list.get(i) ) ){
 88                     flag2++;
 89                 }else if( ")".equals( list.get(i) ) ){
 90                     if(flag2 > 0){
 91                         flag2--;
 92                         continue;
 93                     }else {
 94                         flag1--;
 95                         list.remove(i);
 96                         i--;
 97                     }
 98                 }
 99             }
100         }
101         return StringUtils.join(list.toArray());
102     }
103 
104     /**
105      * 簡單的邏輯文字直接轉換成一個邏輯實體
106      * @param blockContent
107      * @return
108      */
109     private Logic getLogicBySimpleContent(String blockContent) {
110         Logic logic = new Logic();
111         for (int i = 0; i < symbol.length; i++) {
112             if( blockContent.indexOf( symbol[i] ) != -1 ){
113                 String value1 = blockContent.substring(0 , blockContent.indexOf( symbol[i] ));
114                 String value2 = blockContent.substring( blockContent.indexOf( symbol[i] ) + symbol[i].length());
115                 try {
116                     double b = Double.valueOf(value2);
117                     logic.setKey(value1);
118                     logic.setValue(b);
119                     logic.setSymbol(symbol[i]);
120                 }catch (Exception e){
121                     double b = Double.valueOf(value1);
122                     logic.setKey(value2);
123                     logic.setValue(b);
124                     logic.setSymbol(backSymbol[i]);
125                 }
126                 return logic;
127             }
128         }
129         return logic;
130     }
131 }

  2. 根據Logic和json判斷最終結果

 1  public class HandleLogic {
 2     /**
 3      * 根據邏輯樹,遞迴獲取最終的邏輯結果s
 4      */
 5     public boolean handleMessageByLogicCore(Logic logic , JSONObject object ) {
 6         boolean bool = false;
 7         String key = logic.getKey();
 8         if( object.get(key) == null ){
 9             return  this.getLogicByResult(logic , bool , object);
10         }
11         double value = logic.getValue();
12         double realValue = object.getDoubleValue( key );
13         switch ( logic.getSymbol() ){
14             case ">=":
15                 bool = realValue >= value;
16                 break;
17             case "<=":
18                 bool = realValue <= value;
19                 break;
20             case "==":
21                 bool = realValue == value;
22                 break;
23             case "<":
24                 bool = realValue < value;
25                 break;
26             case ">":
27                 bool = realValue > value;
28                 break;
29         }
30         return  this.getLogicByResult(logic , bool , object);
31     }
32 
33     /**
34      * 根據邏輯的結果,獲取邏輯的成功/失敗的子邏輯樹,不存在則直接返回成功/失敗
35      * @param logic 當前邏輯樹
36      * @param b 當前邏輯樹的執行結果
37      * @param object 當前邏輯樹的處理物件
38      * @return
39      */
40     private boolean getLogicByResult(Logic logic, boolean b, JSONObject object) {
41         if( b ){
42             if( logic.getSucLogic() == null ){
43                 return true;
44             }else {
45                 return handleMessageByLogicCore( logic.getSucLogic() , object );
46             }
47         }else {
48             if( logic.getFailLogic() == null ){
49                 return false;
50             }else {
51                 return handleMessageByLogicCore( logic.getFailLogic() , object );
52             }
53         }
54     }
55 }

  以上就是邏輯語句編譯的總結,原創不易,轉載請註明出