基于逻辑表达式的集合运算

来源:互联网 发布:淘宝手写披露函 编辑:程序博客网 时间:2024/06/06 17:39

课题:基于逻辑表达式的集合运算

 

需求:

 实际项目开发中,我们可能会有这样的需求,有A、B、C、D四个集合,需要对这四个集合进行一定的逻辑运算,从而得到经过该表达式运算之后的最终的集合情况。

 

实例:

 1、假设现在有四个集合元素分别为:
 
 A集合:20,50,60
 B集合:70,80
 C集合:90,100
 D集合:30,70,80
 
 2、运算表达式为:(A∪B)∩(C∪D)
 
 3、我们想要的最终集合为:70,80.
 
 A∪B = 20,50,60,70,80
 C∪D = 90,100,70,80,30
 (A∪B)∩(C∪D)= 70,80

 


步骤:

 1、建立操作模型。
 
 逻辑表达式的解析,一般思路就是依据运算符号(包括括号)优先级下坠,构建成树状结构。所以我们建立的模型如下:
 
 LogicExpression{
  LogicExpression left;//左分支
  LogicExpression right;//右分支
  Collection data;//数据集合
 }
 
 2、解析逻辑表达式,根据表达式初始化操作模型的树状结构。
 
 3、根据集合索引,向树状结构的操作模型中各个节点分发数据集合。
 
 4、根据树模型的中序遍历规则,将各个节点的左右俩分支的数据集合进行运算。
 
 5、最后得到根节点的数据集合,即为所求。

 


 
源码:

package tools;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.StringTokenizer;/** * 逻辑表达式或数值表达式的解析成表达式树结构 *  * @author 高伟 * @date May 29, 2012 8:51:49 AM * @description: */public class LogicExpression {  private String separators = "∩∪()"; private String[] operators = { "∩", "∪" };  /*  * 树节点数据  */ private String data = null; /*  * 树节点左分支  */ private LogicExpression left = null; /*  * 树节点右分支  */ private LogicExpression right = null; /*  * 树节点集合数据  */ private Collection<Object> dataList = new ArrayList<Object>();   private String exp = ""; private List<String> parts = new ArrayList<String>(); private int numOperators = 0; public LogicExpression(String exp) throws RuntimeException {  this(exp, "∩∪()", new String[]{ "∩", "∪" }); }  private LogicExpression(String exp, String separators, String[] operators) throws RuntimeException {  this.separators = separators;  this.operators = operators;  this.exp = exp;  splitExpression(exp);  parseSyntax(); }  /**  * 打印解析后表达式树结构,按照前序遍历。  *   * printTree  * 高伟  * May 29, 2012 8:59:43 AM  */ public void printTree() {   System.out.println(data);  if ( left !=null ) left.printTree();   if ( right != null ) right.printTree();  }  /**  * 将集合Map分发到树的每个节点  *   * walkMap  * @param map  * 高伟  * May 29, 2012 9:00:26 AM  */ public void walkMap(Map<String, Collection<Object>> map)    {         if ( left != null ) left.walkMap(map);         if("∩".equals(data) || "∪".equals(data) || "(".equals(data) || ")".equals(data)){  }else{   dataList = map.get(data);  }        if ( right != null ) right.walkMap(map);     }  /**  * 按照先左后右的顺序合并所有节点的集合  *   * combin  * 高伟  * May 29, 2012 9:00:55 AM  */ public void combin() {   if(left != null ){   left.combin();    dataList.addAll(left.dataList);  }  if(right != null ){   right.combin();   if("∩".equals(data)){    dataList.retainAll(right.dataList);   }else if("∪".equals(data)){    dataList.addAll(right.dataList);   }  } } /**  * 分隔表达式  *   * splitExpression  * @param Expression  * 高伟  * May 29, 2012 9:03:55 AM  */ private void splitExpression(String Expression) {  StringTokenizer statements = new StringTokenizer(Expression, separators, true);  String tempToken;  parts.clear();  numOperators = 0;  while (statements.hasMoreElements()) {   tempToken = (String) statements.nextElement();   for (int i = 0; i < operators.length; i++)    if (tempToken.equals(operators[i]))     numOperators++;   parts.add(tempToken);  } } /**  * 解析表达式为树结构  *   * parseSyntax  * @throws RuntimeException  * 高伟  * May 29, 2012 9:04:07 AM  */ private void parseSyntax() throws RuntimeException {  String actToken = "";  int level = 0;  int foundPriority = Integer.MAX_VALUE;  int foundLevel = Integer.MAX_VALUE;  int foundPosition = -1;  String foundOperator = "";  if (numOperators == 0) {   setData((String) parts.get(0));   return;  }  for (int position = 0; position < parts.size(); position++) {   actToken = (String) parts.get(position);   if (actToken.equals("(")) {    level++;    continue;   }   if (actToken.equals(")")) {    level--;    continue;   }   for (int prior = 0; prior < operators.length; prior++)    if (actToken.equals(operators[prior]))     if (level < foundLevel || (level == foundLevel && prior < foundPriority)) {      foundLevel = level;      foundPriority = prior;      foundPosition = position;      foundOperator = actToken;      break;     }  }  if (level != 0)   throw new RuntimeException("parseSyntax error");  if (foundLevel != Integer.MAX_VALUE && foundLevel > 0) {   if (!((String) parts.get(0)).equals("(") || !((String) parts.get(parts.size() - 1)).equals(")"))    throw new RuntimeException("parseSyntax error");   exp = exp.substring(1, exp.length() - 1);   splitExpression(exp);   parseSyntax();   return;  }  String leftPart = "";  String rightPart = "";  for (int i = 0; i < parts.size(); i++)   if (i < foundPosition)    leftPart = leftPart.concat((String) parts.get(i));   else if (i != foundPosition)    rightPart = rightPart.concat((String) parts.get(i));  setData(foundOperator);  if (leftPart.equals("") && !foundOperator.equals("")) {   setRight(new LogicExpression(rightPart));  } else {   setLeft(new LogicExpression(leftPart));   setRight(new LogicExpression(rightPart));  } }  //get set method public String getData() {  return data; } public void setData(String data) {  this.data = data; } public LogicExpression getLeft() {  return left; } public void setLeft(LogicExpression left) {  this.left = left; } public LogicExpression getRight() {  return right; } public void setRight(LogicExpression right) {  this.right = right; }  public Collection<Object> getDataList() {  return dataList; } public void setDataList(Collection<Object> dataList) {  this.dataList = dataList; } @Override public String toString() {  return data; }}

 



测试:

public static void main(String[] args) { {//多层次测试  LogicExpression logExp = new LogicExpression("(A∪B)∩(C∪D)");//1、建立操作模型。2、解析逻辑表达式  logExp.printTree();//打印操作模型。  Map<String, Collection<Object>> map = new HashMap<String, Collection<Object>>();  {   List<Object> list = new ArrayList<Object>();   list.add(new Integer(20));   list.add(new Integer(50));   list.add(new Integer(60));   map.put("A", list);  }  {   List<Object> list = new ArrayList<Object>();   list.add(new Integer(70));   list.add(new Integer(80));   map.put("B", list);  }  {   List<Object> list = new ArrayList<Object>();   list.add(new Integer(90));   list.add(new Integer(100));   map.put("C", list);  }  {   List<Object> list = new ArrayList<Object>();   list.add(new Integer(30));   list.add(new Integer(70));   list.add(new Integer(80));   map.put("D", list);  }  logExp.walkMap(map);//3、根据集合索引,向树状结构的操作模型中各个节点分发数据集合。  logExp.combin();//4、根据树模型的中序遍历规则,将各个节点的左右俩分支的数据集合进行运算。  Collection<Object> list = logExp.getDataList();//5、最后得到根节点的数据集合,即为所求。  for (Object obj : list) {   System.out.println(obj);  } }}

 

 

结果:

7080

 


总结:

 godway
 com.gaowei@msn.com
 2012-07-04

 

 

原创粉丝点击