2016-02-18 31 views
2

我有這樣的代碼:Groovy中 - 奇怪的收藏#相交行爲

def a1 = [[1],[2],[3]] 
def a2 = [[2],[3],[4]] 
a1.intersect(a2) 

和結果有:

[] 

經過研究一段時間後,我發現,數組中的元素必須是實例可比。在DefaultGroovyMethods我們可以看到相貫法的實現。我注意到的第一件事是用於檢查我們列表中的對象存在的集合(TreeSet)(順便說一句,如果HashSet使用它工作正常)。

我檢查了NumberAwareComparator有兩個選項用於檢查compareTo方法。首先是與另一個類的比較委託(吃掉異常?!),第二個是hashCode檢查。

第一個選項DefaultTypeTransformation解釋了我們的行爲。 我們可以看到只有被允許的對象被比較是Comparable,而在其他情況下,我們得到了以後被吃掉的異常。

我的問題是爲什麼它是這樣的?文檔中缺少信息(或者我錯了嗎?)。我錯過了什麼嗎?

+0

它用於返回2.2.1中的預期結果 - 如果你期望'[[2],[3]]'而不是'[]'。也許https://github.com/apache/groovy/commit/4a5bb22d打破了它。 – youri

回答

0

找不到記錄。

感覺像是對github上的項目有很大的拉動請求貢獻,改變了現有的文檔/ javadoc以使其更加明確嗎?

元素必須具有可比性,否則無法比較它們以檢查交叉點,但是您說得對,文檔不是明確的。

你可以寫自己的實現,像這樣:

Collection.metaClass.equalityIntersect = { Collection other -> 
    delegate.findAll { a -> other.find { it == a } } 
} 

這樣a1.equalityIntersect(a2) == [[2], [3]]

+0

如果檢查交叉點,我是否真的需要比較元素(通過使用Comparable)?不能用HashSet而不是TreeSet來完成? – hexin

+0

您可以向Collection的metaClass添加一個方法(請參閱編輯的答案)...不確定Groovy會接受此方法的更改,因爲它會改變現有功能,但它可能是值得提出的問題 –

+0

我嘗試過很少,該解決方案的工作原理如下:List.metaClass.compareTo = {Collection other - > delegate [0] <=> other [0] } def arr1 = [[1],[2],[3],[5 ]]。collect {it Comparable} def arr2 = [[4],[2],[3],[6],[5]]。結果:[[2],[3],[5]] – hexin

0

此行爲已出臺的地方向下行 - 沒有針指向它,也許2.4.22.4.2作爲每this commit。它曾經在2.2.12.4.0中工作,並在2.4.6上被破壞...但它在2.4.7中被修復。

$ groovy -v 
Groovy Version: 2.4.7 JVM: 1.8.0_92 Vendor: Oracle Corporation OS: Mac OS X 
$ groovy intersect.groovy 
[[2], [3]] 

這樣的變化如何推出到發佈對我來說是一個謎。缺乏測試?