有效地比较列表/对象集

时间:2017-06-14 21:15:35

标签: java list oop set software-design

我正在尝试比较两个Fact数据结构。

每个Fact由谓词和参数列表组成

private String predicate;
private ArrayList<Argument> arguments;

Argument类由变量和符号

组成
String variable;
argTypes symbol;

public enum argTypes {
    STRING, EQ, GT, LT, MATCHONE, MATCHALL, VAR
}

有两个子类numericArgumentstringArgument

private boolean isNeg;
private int value; //or private String value if stringArgument

数字参数示例:length = 10, length != 10, length > 10, length < 10

字符串参数示例:length = long, length != long

参数也可能具有?的值(仅与一个参数匹配),*(匹配0或更多参数),&x(变量) - 我将这些构造为通用的Argument类型,设置适当的symbol字段

所以进入匹配!良好匹配的例子:

带有cat(height = tall, colour = black, length=30)

cat(height = tall, colour = black, length>20)

cat(black) cat(!brown)

Cat(fur = soft, colour = brown, size = 10)匹配Cat(fur = soft, *)

不良比赛的例子:

带有Cat(fur = soft, colour = brown, size = 10)

Cat(fur = soft, colour = brown) [缺少的参数完全定义了不同的谓词]

我已经实现了匹配两个Argument对象的方法,但我正在努力实现比较两个Fact对象的好方法。我已经尝试使用Hashset和LinkedHashSet而不是参数arraylist。我还尝试向containsMatchAll添加Fact字段,而不是在参数列表中包含*

我非常感谢有关如何彻底检查此数据结构的建议,以便匹配不会超级慢。

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以考虑转换

private ArrayList<Argument> arguments;

进入地图,说

private HashMap<String, Argument> arguments;

其中,映射中的每个条目都是一个键:值对,由参数/变量名称和值为参数引用组成。

然后,在比较两个不同对象的Arguments时,您可以迭代第一个对象的Argument映射的键:

if (object1.getArguments().size() != object2.getArguments.size()) {
   ... // they don't even have the same number of arguments, this is the first check
} else {

    for(String variableName : object1.getArguments().keySet()) {
        if(!object2.getArguments().contains(variableName)) {
            ... // bad match !
            break;
        } else {
           Argument arg1 = object1.getArguments().get(variableName);
           Argument arg2 = object2.getArguments().get(variableName);
           ... // do some comparison here
        }
    }
}

这可以防止对象包含具有相同名称的重复变量。

这实际上是程序员应该采取的设计决策。我应该添加一个免责声明,这不是解决此问题的唯一方法,这只是其中之一,但对于您要执行的操作来说非常方便。