简体   繁体   中英

Equals implementation in a java-class which implements an interface that extends Iterable?

How would one implement equals in a java-class which implements an interface that extends Iterable?

The interface

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

The concrete class

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) {

How should I check that both this instance and the other instances contains the same set of strings? The easy way would to only check equals against this implementation and not the interface, but that sounds like cheating.

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

but

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

Or am I missing something? I must implement hashCode aswell, and if two objects are equal should not their hashcodes be identical hence equals must only check against MyClass to fullfil this contract?!

  }

}

One way would be to use Guava Iterables.elementsEqual method.

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);
}

When comparing Sets, a Collection (its super-interface) will never be equals even if it contains the same objects.

If two classes are equal, they must have the same hashCode(). Its is worth noting that HashSet is not ordered and two sets with the same elements can be in different orders.

So if you have only an Iterator, you have to add all the elements to a Set, before you do the comparison in any case.

As an experiment I generated some combinations you can get with the same Set.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM