2011-09-07 108 views
0

在一個實現了一個擴展Iterable接口的java類中,如何實現equals?在實現可擴展Iterable的接口的java類中等於實現?

接口

public interface MyInterface extends Iterable<String> { 
... 
} 

具體類

public class MyClass implements MyInterface { 

    private Set<String> myStrings = new HashSet<String>(); 

    @Override 
    public Iterator<String> iterator() { 
    return myStrings.iterator(); 
    } 

    @Override 
    public boolean equals(Object otherObject) { 

我應該如何檢查這兩個實例和其它實例包含了一組字符串?簡單的方法將只檢查等於這個實現而不是界面,但這聽起來像是作弊。

if (otherObject instanceof MyClass) { ... } // easy, just myStrings.equals(...) 

if (otherObject instanceof MyInterface) { ... } // compare two iterators? 

還是我失去了一些東西?我也必須實現hashCode,如果兩個對象相同,不應該他們的哈希碼相同,因此等於只能檢查MyClass來滿足這個合同?!

} 

} 

回答

2

一種方法是使用Guava Iterables.elementsEqual方法。

http://docs.guava-libraries.googlecode.com/git-history/release09/javadoc/com/google/common/collect/Iterables.html#elementsEqual(java.lang.Iterable, java.lang.Iterable)

/** 
* Returns true if all elements in <code>searchFor</code> exist in 
* <code>searchIn</code>, otherwise returns false. 
* 
* @param searchIn 
*   the collection in which to search for each element in 
*   <code>searchFor</code> 
* @param searchFor 
*   the collection of element to search for 
*/ 
public static boolean containsAll(@Nonnull Iterable<?> searchIn, @Nonnull Iterable<?> searchFor) { 
    for (Object o : searchFor) { 
     if (!Iterables.contains(searchIn, o)) { 
      return false; 
     } 
    } 
    return true; 
} 

/** 
* Returns true if all elements in <code>searchFor</code> exist in 
* <code>searchIn</code> and no other elements exist in 
* <code>searchIn</code>, otherwise returns false. 
* 
* @param searchIn 
*   the collection in which to search for each element in 
*   <code>searchFor</code> 
* @param searchFor 
*   the collection of element to search for 
*/ 
public static boolean containsAllAndOnly(@Nonnull Iterable<?> searchIn, 
     @Nonnull Iterable<?> searchFor) { 
    if (Iterables.size(searchIn) != Iterables.size(searchFor)) { 
     return false; 
    } 

    return containsAll(searchIn, searchFor); 
} 
+0

作爲集合是無序的,有這種方法的一個無序版本實驗? –

+0

不在Guava圖書館(我知道)。我有自己的Guava附加組件,它實現了containsAll,它遍歷一個迭代器並在另一個迭代器上調用Iterables.contains。使用上面描述的Set機制可能會更高效。 –

+0

我還創建了一個containsAllAndOnly,它使用Iterables.size檢查每個Iterable的大小是否相同,然後調用containsAll。 –

2

當比較集合,集合(其超接口)將永遠不會等於即使它包含了相同的對象。

如果兩個類相等,它們必須具有相同的hashCode()。值得注意的是,HashSet不是有序的,並且具有相同元素的兩個集合可以以不同的順序排列。

所以如果你只有一個迭代器,你必須將所有元素添加到一個集合,然後再進行比較。

正如我生成some combinations you can get with the same Set.

+0

如果Iterable包含等值對象的多個實例,則必須小心使用Set機制。一個集合會將這些集合摺疊成一個實例,所以多重性將會丟失。 –

+0

@John B,確實如此,但是比較Set和List並不是直截了當的。 (集合不能有重複)這就是爲什麼JDK假定集合和列表從不相等的原因。 (甚至是空的) –

+0

因此,基本上檢查來自其他對象迭代器的所有元素都存在於這個集合中,並且這個集合不包含更多(由@John包含的containsAllAndOnly方法)。 – Axel