Reputation: 199
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:
So I wonder what is the better way to organize such equals() redefinition on the fly during program execution?
Upvotes: 2
Views: 132
Reputation: 3412
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.
Upvotes: 3
Reputation: 168232
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.
Upvotes: 1