2015-06-24 61 views
4

Java documentation如何檢測如果列表中包含本身的Java

注:雖然列表允許把自身作爲元素包含,格外小心,建議:在平等和hashCode方法不再明確定義在這樣的名單上。

問題是List對象的哈希碼是遞歸計算的。

int hashCode = 1; 
for (E e : list) 
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 

的問題是如何使我的白癡證明和檢測表對象(或它的一些項目甚至更深的)是否包含列表對象本身。

如何在遍歷List對象時能夠保持List對象列表並且能夠調用contains()方法?是保持System.identityHashCode(對象)和測試反對它足夠好?

+0

您是否定義了自己的列表類型?當另一個啓動時,你可以檢測列表是否已經處於「equals」或「hashCode」調用的中間,但是在多線程環境中正常工作會變得棘手。如果你需要處理像ArrayLists這樣的東西,這是否可能取決於你需要處理的元素類型。如果一個列表元素有一個包含你的列表的私有字段,你可能永遠不會知道。 – user2357112

回答

4

System.identityHashCode會有幫助,但使用其中一個內置工具通過身份跟蹤對象幾乎肯定會更簡單 - IdentityHashMap

boolean containsCircularReference(Iterable<?> iterable) { 
    return containsCircularReference(
    iterable, 
    Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>())); 
} 

private boolean containsCircularReference(Object o, Set<Object> seen) { 
    if (seen.contains(o)) { 
    return true; 
    } 
    seen.add(o); 
    if (o instanceof Iterable) { 
    for (Object o2 : (Iterable<?>) o) { 
     if (containsCircularReference(o2, seen)) { 
     return true; 
     } 
    } 
    } 
    return false; 
} 

作爲參考,你不能依靠System.identityHashCode是無碰撞。對於初學者來說,你可以在JVM分配超過2^32個對象,而且只有2^32個不同的identityHashCode S可能...

如果它不只是在Iterable成員,但任何循環引用都,這會變得更加困難,雖然可以反思。也就是說,這種循環引用的存在並不一定意味着equalshashCode將不起作用;只要equalshashCode方法中的參考文獻是非循環的,並且沒有檢測該方法的通用方法,循環參考就完全可以。

+0

打敗我吧。很好的答案! – templatetypedef

相關問題