Question

Suppose I have a Point class with fields x,y,z,name. Objects of this class must be inserted in a Hash Set in two different ways depending on the user choice:

  • equals() checks equality of x,y,z fields
  • equals() checks equality of x,y,z,name fields

So I wonder what is the better way to organize such equals() redefinition on the fly during program execution?

Was it helpful?

Solution 2

If you can change from using HashSet to a TreeSet and add a custom comparator:

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

Running this:

public static void main( final String[] args ){
    Point[] pts = {
            new Point( 1, 1, 1, "1" ),
            new Point( 2, 2, 2, "2" ),
            new Point( 3, 3, 3, "3" ),
            new Point( 1, 1, 1, "4" ),
            new Point( 4, 4, 4, "2" )
    };

    TreeSet<Point> ps = new TreeSet<Point>();
    for ( Point p : pts )
        ps.add( p );
    System.out.println( ps );
}

Gives an output of

[(1.0,1.0,1.0,1), (2.0,2.0,2.0,2), (3.0,3.0,3.0,3)]

So the last two values are not entered into the TreeSet as they are rejected by the comparator.

OTHER TIPS

You can create 2 Classes: Point and NamedPoint and override the equals() and hashcode() methods.

Here is an example in pseudo code:

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

class NamedPoint extends Point{
   equals{
   }
   hashCode{
   }
}

Another option is to use one class, but add a new boolean switch, which changes the behavior of equals and hashCode.

P.S. I recommend you to read What issues should be considered when overriding equals and hashCode in Java?. You must be careful overriding these methods. It is useful to use the eclipse feature "Source --> Generate hashCode() and equals().." and after that to change the behavior of the generated methods.

P.S.2: Grigory Kalabin's link describes, what are the problems that might occure doing this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top