基于闭包比较两个无序的对象列表

时间:2014-11-07 23:36:27

标签: java list groovy

我有两个无序列表。我想要做的是根据我可以通过闭包/指针函数指定的一些条件来比较这两个列表。

我遇到的问题是这些列表中的对象结构可能不同,我想在某些情况下比较某些属性,而在其他情况下比较其他属性。

e.g。

Class sampleObj{
    String attribute1;
    List attribute2;
    String attribute3;
}

List A
 Obj1-> attribute1 = "test",attribute2 = ["a","b","c"]
 Obj2 -> attribute1 = "optionalArg test 2",attribute3 = "optionalArg"

List B
Obj1 -> attribute3 = "test4", attribute2 = [1,2,3]
Obj2 -> attribute3 = "optionalArg"
Obj3 -> attribute1 = "test",attribute2 = ["a","b","c"]

在这种情况下,列表A中的对象1等于列表B中的对象3(对象的所需属性都相等),列表A中的对象2等于列表B中的对象2(属性3的值是属性1)的子字符串。

因此,我的条件可以基于属性1和属性2或属性3的交叉积。 意味着如果属性1和属性2对于ListA中的对象1和来自ListB的对象3是相等的,我们可以说这两个对象是相等的,否则如果属性3匹配属性1的某些条件,那么我们可以说对象是相等的意思是对象2来自listB可以等于列表A中的object2(在这种情况下条件是子字符串检查)

一般情况下,我试图编写这个带有两个列表和闭包的库方法,然后基于传递的闭包让我知道列表A中的某些对象是否与列表B匹配,反之亦然。

请告诉我这里是否有任何问题/澄清或/和您是否可以指导我朝正确的方向发展。

2 个答案:

答案 0 :(得分:1)

如果你想知道的是,根据任意标准,两个列表之间是否存在匹配,那么您需要的只是以下内容:

def hasMatches(List a, List b, Closure<Boolean> matchCriteria) {
  a && b && a.any{ aa -> b.any { bb -> matchCriteria(aa, bb) || matchCriteria(bb, aa) } }
}

然后以下断言都返回true:

class SampleObj{
  String attribute1
  List attribute2
  String attribute3
  String name

  @Override String toString() { name }
}

List<SampleObj> listA = [
    [name: "ObjA1", attribute1: "test", attribute2: ["a","b","c"]] as SampleObj,
    [name: "ObjA2", attribute1: "optionalArg test 2", attribute3: "optionalArg"] as SampleObj
]

List<SampleObj> listB = [
    [name: "ObjB1", attribute3: "test4", attribute2: [1,2,3]] as SampleObj,
    [name: "ObjB2", attribute3: "optionalArg"] as SampleObj,
    [name: "ObjB3", attribute1: "test", attribute2: ["a","b","c"]] as SampleObj
]

// there exists at least one object in list A whose attribute 1 value matches that of at least one object in list B (or vice versa)
assert hasMatches(listA, listB) { SampleObj aa, SampleObj bb -> aa?.attribute1 == bb?.attribute1 }

// there exists at least one object in list B whose attribute 3 value is a substring of the attribute 1 value of at least one object in list A (or vice versa)
assert hasMatches(listA, listB) { SampleObj aa, SampleObj bb -> bb?.attribute3 && aa?.attribute1?.contains(bb.attribute3) }

// there does not exist any object in list A whose attribute 1 value is contained in the attribute 2 list of any object in list B (or vice versa)
assert !hasMatches(listA, listB) { SampleObj aa, SampleObj bb -> aa?.attribute1 && bb?.attribute2?.contains(aa.attribute1) }

另一方面,如果你真的想看到匹配的对,那么你需要更广泛的东西:

def findEquivalentPairs(List a, List b, Closure<Boolean> matchCriteria) {
  a && b \
    ? a.sum { aa ->
      def ab = b.findResults { bb -> matchCriteria(aa, bb) ? [aa, bb] : null } ?: []
      def ba = b.findResults { bb -> matchCriteria(bb, aa) ? [bb, aa] : null } ?: []
      ab + ba
    }
    : []
}

然后,使用相同的三个标准闭包打印出结果......

println findEquivalentPairs(listA, listB) { SampleObj aa, SampleObj bb -> aa?.attribute1 == bb?.attribute1 }
println findEquivalentPairs(listA, listB) { SampleObj aa, SampleObj bb -> bb?.attribute3 && aa?.attribute1?.contains(bb.attribute3) }
println findEquivalentPairs(listA, listB) { SampleObj aa, SampleObj bb -> aa?.attribute1 && bb?.attribute2?.contains(aa.attribute1) }

......产生以下结果:

[[ObjA1, ObjB3], [ObjB3, ObjA1]]
[[ObjA2, ObjB2]]
[]

答案 1 :(得分:0)

通常,您可以使用Comparable来实现此目的。

Comparable接口定义了一个compareTo()函数,您可以实现该函数以实现您需要的任何比较逻辑。

或者,只需覆盖equals()方法。