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

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

 

需求:

 实际项目开发中,我们可能会有这样的需求,有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);
  }
 }
}

 

 

结果:

70
80

 


总结:

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

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值