Java 对同一类应用不同的相等项

Java 对同一类应用不同的相等项,java,equals,hashset,Java,Equals,Hashset,假设我有一个点类,它的字段是x,y,z,name。 此类的对象必须以两种不同的方式插入哈希集中,具体取决于用户选择: 等于检查x、y、z字段的相等性 等于检查x、y、z和名称字段的相等性 因此,我想知道在程序执行过程中动态组织这些equals重新定义的更好方法是什么?您可以创建两个类:Point和NamedPoint,并重写equals和hashcode方法 下面是一个伪代码示例: class Point{ String name int x,y,z equals{

假设我有一个点类,它的字段是x,y,z,name。 此类的对象必须以两种不同的方式插入哈希集中,具体取决于用户选择:

等于检查x、y、z字段的相等性 等于检查x、y、z和名称字段的相等性 因此,我想知道在程序执行过程中动态组织这些equals重新定义的更好方法是什么?

您可以创建两个类:Point和NamedPoint,并重写equals和hashcode方法

下面是一个伪代码示例:

class Point{
   String name
   int x,y,z
   equals{
     ...
   }
   hashCode{
     ...
   }
}

class NamedPoint extends Point{
   equals{
   }
   hashCode{
   }
}
另一种选择是使用一个类,但添加一个新的布尔开关,这会更改equals和hashCode的行为

另外,我建议你阅读。您必须小心重写这些方法。使用eclipse特性Source->Generate hashCode and equals非常有用。。然后更改生成方法的行为

p.S.2:Grigory Kalabin描述了这样做可能出现的问题。

您可以创建两个类:Point和NamedPoint,并重写equals和hashcode方法

下面是一个伪代码示例:

class Point{
   String name
   int x,y,z
   equals{
     ...
   }
   hashCode{
     ...
   }
}

class NamedPoint extends Point{
   equals{
   }
   hashCode{
   }
}
另一种选择是使用一个类,但添加一个新的布尔开关,这会更改equals和hashCode的行为

另外,我建议你阅读。您必须小心重写这些方法。使用eclipse特性Source->Generate hashCode and equals非常有用。。然后更改生成方法的行为


p.S.2:Grigory Kalabin描述了这样做可能出现的问题。

如果您可以从使用哈希集更改为树集并添加自定义比较器:

public class Point implements Comparable<Point> {
    private double x;
    private double y;
    private double z;
    private String name;

    public Point( final double x, final double y, final double z, final String name ) {
        setX( x );
        setY( y );
        setZ( z );
        setName( name );
    }

    public boolean equals( final Point point ){
        final boolean isEqual =
                (   this.getX() == point.getX()
                &&  this.getY() == point.getY()
                &&  this.getZ() == point.getZ() )
            ||  (   this.getName().equals( point.getName() ) );
    //  System.out.println( this.toString() + " == " + point.toString() + " = " + isEqual );
        return isEqual;
    }

    /// @return the x
    public double getX() { return x; }
    /// @return the y
    public double getY() { return y; }
    /// @return the z
    public double getZ() { return z; }
    /// @return the name
    public String getName() { return name; }
    /// @param x the x to set
    public void setX(final double x) { this.x = x; }
    /// @param y the y to set
    public void setY(final double y) { this.y = y; }
    /// @param z the z to set
    public void setZ(final double z) { this.z = z; }
    /// @param name the name to set
    public void setName(final String name) { this.name = name; }

    public String toString() {
        final StringBuffer str = new StringBuffer();
        str.append( '(' );
        str.append( getX() );
        str.append( ',' );
        str.append( getY() );
        str.append( ',' );
        str.append( getZ() );
        str.append( ',' );
        str.append( getName() );
        str.append( ')' );
        return str.toString();
    }

    public double distanceFromOriginSquared(){
        return this.getX()*this.getX()
                + this.getY()*this.getY()
                + this.getZ()*this.getZ();
    }

    @Override
    public int compareTo( final Point point ) {
        if ( this.getName().equals( point.getName() ) )
            return 0;
        final double td = this.distanceFromOriginSquared();
        final double pd = point.distanceFromOriginSquared();
        if ( td < pd ) return -1;
        if ( td > pd ) return +1;
        if ( this.getX() < point.getX() ) return -1;
        if ( this.getX() > point.getX() ) return +1;
        if ( this.getY() < point.getY() ) return -1;
        if ( this.getY() > point.getY() ) return +1;
        return 0;   
    }
}

因此,最后两个值不会输入到树集,因为它们被比较器拒绝。

如果您可以从使用HashSet更改为树集并添加自定义比较器:

public class Point implements Comparable<Point> {
    private double x;
    private double y;
    private double z;
    private String name;

    public Point( final double x, final double y, final double z, final String name ) {
        setX( x );
        setY( y );
        setZ( z );
        setName( name );
    }

    public boolean equals( final Point point ){
        final boolean isEqual =
                (   this.getX() == point.getX()
                &&  this.getY() == point.getY()
                &&  this.getZ() == point.getZ() )
            ||  (   this.getName().equals( point.getName() ) );
    //  System.out.println( this.toString() + " == " + point.toString() + " = " + isEqual );
        return isEqual;
    }

    /// @return the x
    public double getX() { return x; }
    /// @return the y
    public double getY() { return y; }
    /// @return the z
    public double getZ() { return z; }
    /// @return the name
    public String getName() { return name; }
    /// @param x the x to set
    public void setX(final double x) { this.x = x; }
    /// @param y the y to set
    public void setY(final double y) { this.y = y; }
    /// @param z the z to set
    public void setZ(final double z) { this.z = z; }
    /// @param name the name to set
    public void setName(final String name) { this.name = name; }

    public String toString() {
        final StringBuffer str = new StringBuffer();
        str.append( '(' );
        str.append( getX() );
        str.append( ',' );
        str.append( getY() );
        str.append( ',' );
        str.append( getZ() );
        str.append( ',' );
        str.append( getName() );
        str.append( ')' );
        return str.toString();
    }

    public double distanceFromOriginSquared(){
        return this.getX()*this.getX()
                + this.getY()*this.getY()
                + this.getZ()*this.getZ();
    }

    @Override
    public int compareTo( final Point point ) {
        if ( this.getName().equals( point.getName() ) )
            return 0;
        final double td = this.distanceFromOriginSquared();
        final double pd = point.distanceFromOriginSquared();
        if ( td < pd ) return -1;
        if ( td > pd ) return +1;
        if ( this.getX() < point.getX() ) return -1;
        if ( this.getX() > point.getX() ) return +1;
        if ( this.getY() < point.getY() ) return -1;
        if ( this.getY() > point.getY() ) return +1;
        return 0;   
    }
}

因此,最后两个值不会输入到树集中,因为它们会被比较器拒绝。

一个类中不能有两个相等值。但是您可以继承一个新类并重写equals。听起来您可以使用equals和equalsWithName两个方法,也可以使用Point和NamedPoint两个类……您可以有一个子类,通过比较名称来扩展其超类的equal方法。依我看,equals应该检查所有成员。对于任何其他特定检查,您都需要手动比较这些值。@vikingsteve HashSet不会调用equalsWithName。它只能调用equals。对吧?一个班里不能有两个相等的人。但是您可以继承一个新类并重写equals。听起来您可以使用equals和equalsWithName两个方法,也可以使用Point和NamedPoint两个类……您可以有一个子类,通过比较名称来扩展其超类的equal方法。依我看,equals应该检查所有成员。对于任何其他特定检查,您都需要手动比较这些值。@vikingsteve HashSet不会调用equalsWithName。它只能调用equals。对吗?还要注意这样的层次结构可能会破坏equals的对称属性:例如,Point p.equalsanotherPoint不应该与NamedPoint p.equalsanotherPoint相同,Point.equalsanotherPoint与NamedPoint.equalspoint相同吗?还要注意这样的层次结构可能会破坏equals的对称属性:例如,点p.equalsanotherPoint不应该与命名点p.equalsanotherPoint相同,点.equalsanotherPoint不应该与命名点.equalspoint相同吗?