10

为什么在 Groovy 中,当我创建 2 个列表时,如果我执行 a.intersect(b) 和 b.intersect(a) 会有区别:

def list1 = ["hello", "world", "world"];
def list2 = ["world", "world", "world"];

println( "Intersect list1 with list2: " + list1.intersect( list2 ) );
println( "Intersect list2 with list1: " + list2.intersect( list1) );

痕迹:

Intersect list1 with list2: [world, world, world]
Intersect list2 with list1: [world, world]

(如果你想测试它,你可以在这里复制它:http ://groovyconsole.appspot.com/)

如果数组都包含唯一元素,那么它可以正常工作。一旦开始添加重复项,就会变得很奇怪:

def list1 = ["hello", "world", "test", "test"];
def list2 = ["world", "world", "world", "test"];

println( "Intersect list1 with list2: " + list1.intersect( list2 ) );
println( "Intersect list2 with list1: " + list2.intersect( list1 ) );

痕迹:

Intersect list1 with list2: [world, world, world, test]
Intersect list2 with list1: [world, test, test]

我认为重点intersect()是给你共同的元素,所以你把它们放在哪个顺序都没有关系?

如果不是这种情况,我怎样才能只获取公共元素(期望数组中的重复项)。例如,示例一应该返回["world", "world"],示例二应该返回["world", "test"]

编辑

为了澄清一点,这段代码应该测试用户数据是否仍然相同(假设他们在某事中间断开连接,我们要确保数据没有被篡改,或者处于与以前相同的状态)。

无法保证列表的顺序(用户可以对其重新排序,但从技术上讲它仍然是“相同的”),并且可能出现重复。

所以像:["one", "one", "two"]应该匹配["two", "one", "one"],而列表中的任何添加或数据更改都不应该匹配。

4

1 回答 1

14

如果查看的源代码Collection.intersect,您可以看到该方法的逻辑遵循以下流程:

对于两个集合,leftright

  1. 交换leftright如果left小于right
  2. 将所有内容添加left到集合中(删除重复项)
  3. 对于 中的每个元素,right如果它存在于 中leftSet,则将其添加到结果中

因此,对于您的最后两个示例;

def array1 = ["hello", "world", "test", "test"]
def array2 = ["world", "world", "world", "test"]

array1.intersect( array2 )会给出(如果我们在 Groovy 中编写相同的算法):

leftSet = new TreeSet( array1 ) // both same size, so no swap
// leftSet = [ 'hello', 'world', 'test' ]
right   = array2
result = right.findAll { e -> leftSet.contains( e ) }

哪个(如果你运行它),你可以看到意味着结果具有价值[world, world, world, test](如你所见)。这是因为其中的每个元素right都可以在leftSet

不知道为什么第一个示例应该返回["world","world"]...

之后...

所以,我认为你正在寻找的是这样的:

def array1 = ["hello", "world", "test", "test"]
def array2 = ["world", "world", "world", "test"]
def intersect1 = array1.intersect( array2 ) as TreeSet
def intersect2 = array2.intersect( array1 ) as TreeSet
assert intersect1 == intersect2

为了您处理集合中的重复项,然后两者intersect1intersect2将等于

[test, world]

后来还是

我相信这可以满足您的要求:

[array1,array2]*.groupBy{it}.with { a, b -> assert a == b }
于 2011-09-12T11:34:53.597 回答