通用深度比较等于

时间:2009-09-01 14:47:12

标签: java generics

基本上我不想比较元素,而是你所包含的元素。如果追随会起作用会很酷,但事实并非如此。

public boolean equals(Ie<T> that) {
    T This = this.value;
    T That = that.value;
    boolean x = That.compareTo(This) == 0;
    return x;
}

我所做的是:

public boolean equals(Object obj) {
    if (obj == null)
        return false;

    String tmp = obj.toString();
    if (this.value instanceof Integer)
        return equalsInt(new Ie<Integer>(Integer.parseInt(tmp)));
    // etc.

    return false;
}

public boolean equalsInt(Ie<Integer> ie) {
    Integer This = this.value.intValue();
    Integer That = ie.value;
    boolean x = That.compareTo(This) == 0;
    return x;
}

这是一个明显的暴力解决方案。可以在没有 obj.toString(); +新元素吗?

的情况下完成

编辑:

Class Ie定义为:

public static class Ie<T extends Number & Comparable<? super T>>
        extends Number implements Comparable<Ie<T>> {

与方法相比,Class相当简单:

public int compareTo(Ie<T> that) {
    T This = this.value;
    T That = that.value;
    return (This.compareTo(That) < 0 ? -1 : (This
            .compareTo(That) > 0 ? 1 : 0));
}

我在Collection addall方法中使用该类,其中contains包含调用equals。

Erikson解决方案运行良好:

@Override
public boolean equals(Object that) {
    if (that == null)
        return false;
    if (this == that)
        return true;
    if (that instanceof Ie<?>) {
        Object ThisValue = this.value;
        Object ThatValue = ((Ie<?>) that).value;
        return ThisValue.equals(ThatValue);
    }

    return false;
}

5 个答案:

答案 0 :(得分:1)

为此,每个类型T必须实现Comparable接口,并且实现Comparable的每个类都应以一致的方式实现equals。所以,Matt Ball's回答就足够了。

但是,如果由于某种原因它没有,则需要一个适用于Java类型擦除的解决方案。通过显式指定T的类型,可以进行必要的类型检查。 Ie类可以部分定义如下:

class Ie<T extends Comparable<T>>
{

  private final Class<? extends T> type;

  private final T value;

  public Ie(Class<? extends T> type, T value)
  {
    this.type = type;
    this.value = value;
  }

  @Override
  public boolean equals(Object obj)
  {
    if (obj == this)
      return true;
    if (obj instanceof Ie) {
      Object that = ((Ie<?>) obj).value;
      if (type.isInstance(that)) {
        return value.compareTo(type.cast(that)) == 0;
      }
    }
    return false;
  }

}

答案 1 :(得分:0)

@Override
public boolean equals(Object that)
{
    if (this == that)
      return true;
    if (that instanceof Ie) {
      Object ThisValue = this.value;
      Object ThatValue = ((Ie<?>) that).value;
      return ThisValue.equals(ThatValue);
    } else 
      return false;
}

答案 2 :(得分:0)

首先,不要将equals()与compareTo()混淆。第一个显示两个对象是否相等。比较另一方面试图找到哪个更大(在排序时有用)。

比较介绍了相对论的一个要素。例如,如果您有一个Person对象列表,那么如果您按名称比较它们,则“Allun”小于“Dave”,但如果您按年龄对它们进行比较,它们可能相等。即使它们在年龄方面相同,但根据equals()方法它们并不相同,因为它们代表不同的人。

关于equals()方法本身,这可能会对您有所帮助:

class MyClass {

  int anInt;

  public boolean equals(Object obj) {
    if (obj instance of MyClass) {
      MyClass that = (MyClass) obj;
      return this.anInt==that.anInt;
    }
    return false;
  }
}

或者,如果您有另一个对象并且想要检查null:

class MyClass {

  Object anObject;

  public boolean equals(Object obj) {
    if (obj instance of MyClass) {
      MyClass that = (MyClass) obj;
      return this.anObject==null ? that.object==null : this.object.equals(that.object);
    }
    return false;
  }
}

答案 3 :(得分:0)

是的,最简单的方法是使用Object.equals方法来比较包含的对象(如Matt Ball的答案)。 但是,如果由于某种原因无法使用它,则必须存储类型并进行一些动态类型转换(如erickson的答案),或者执行未选中的转换,如下例所示:

class Ie<T extends Comparable<T>>
{
    public Ie(T value) {this.value = value;}

    private final T value;

    public boolean equals(Object obj) {
        if(obj == this)
            return true;

        if(obj instanceof Ie<?>)
        {
            Ie<?> That = (Ie<?>)obj;

            if(value.getClass() != That.value.getClass())
                return false;

            // Cast to anything that allows calling typed equals(). 
            // The type will be erased at runtime anyway.
            return ((Ie<String>)this).equals((Ie<String>)That); 
        }
        return false;
    }

    public boolean equals(Ie<T> that)
    {
        return that.value.compareTo(this.value) == 0;
    }
}

答案 4 :(得分:0)

如果您尝试比较通用参数类型的实例,请考虑Ie<String>Ie<Integer>将抛出ClassCastException

我将建议对erickson略有不同的解决方案。如果我们向Comparator添加Ie,我们可以委派比较。

在缺点方面,这确实需要您创建Comparator(可能已定义equals)并且您不得以不安全的情况获取Comparator实例(例如, Collections.emptyList确实如此)。

class Ie<T> {

    private final Comparator<? super T> comparator;

    private final T value;

    public Ie(Comparator<? super T> comparator, T value) {
        if (comparator == null || value == null) {
            throw new NullPointerException();
        }
        this.comparator = comparator;
        this.value = value;
    }

    @SuppressWarnings("unchecked")
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Ie)) {
            return false;
        }
        Object other = (Ie<?>)obj;
        return
             this.comparator.equals(other.comparator) &&
             this.comparator.compare(this.value, (T)other.value) == 0
    }

    @Override
    public int hashCode() {
        return comparator.hashCode()*31 + value.hashCode();
    }
}