假设我有一个包含字段x,y,z,name的Point类。 必须根据用户选择以两种不同的方式将此类的对象插入哈希集:
所以我想知道在程序执行期间动态组织这种equals()重新定义的更好方法是什么?
答案 0 :(得分:3)
您可以创建2个类:Point
和NamedPoint
并覆盖equals()
和hashcode()
方法。
以下是伪代码中的示例:
class Point{
String name
int x,y,z
equals{
...
}
hashCode{
...
}
}
class NamedPoint extends Point{
equals{
}
hashCode{
}
}
另一种选择是使用一个类,但添加一个新的布尔开关,它会改变equals
和hashCode
的行为。
P.S。我建议你阅读What issues should be considered when overriding equals and hashCode in Java?。你必须小心重写这些方法。使用eclipse功能“Source - > Generate hashCode()和equals()..”并在此之后改变生成方法的行为是很有用的。
P.S.2:Grigory Kalabin的link描述了这样做可能会出现的问题。
答案 1 :(得分:1)
如果您可以使用HashSet
更改为TreeSet
并添加自定义比较器:
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;
}
}
运行此:
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 );
}
输出
[(1.0,1.0,1.0,1), (2.0,2.0,2.0,2), (3.0,3.0,3.0,3)]
因此,最后两个值未输入TreeSet
,因为它们被比较器拒绝。