2011-09-07 103 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