有效地比较 list/set 个对象

Comparing a list/set of objects efficiently

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

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

private String predicate;
private ArrayList<Argument> arguments;

Argument class由一个变量和一个符号组成

String variable;
argTypes symbol;

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

有两个子classes 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

arguments 也可能有值 ?(只匹配一个参数),*(匹配 0 个或多个参数),&x(一个变量)- 我构造这些作为通用参数类型,设置它们适当的 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 而不是在参数列表中包含 *

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

谢谢!

您可以考虑转换

private ArrayList<Argument> arguments;

进入地图,说

private HashMap<String, Argument> arguments;

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

然后,当比较两个不同对象的 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
        }
    }
}

这有额外的好处,您可以防止对象包含具有相同名称的重复变量。

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