Java – how to implement the equals / hashcode method for a class with two fields

I override equals and hashcode in a class that contains two fields My first method is to use epsilon test in equals method and double in hashcode Hashcode (double), but this will result in equal objects with different hash codes; This is a simplified example:

public class DoubleHashTest2
{
    public static void main(String[] args)
    {
        double  base1   = .9;
        double  base2   = .7;
        Test    test1   = new Test( base1 - .1 );
        Test    test2   = new Test( base2 + .1 );

        System.out.println( test1.equals( test2 ) );
        System.out.println( test1.hashCode() );
        System.out.println( test2.hashCode() );
    }

    private static class Test
    {
        private double  dnum1;

        public Test( double dnum1 )
        {
            this.dnum1 = dnum1;
        }

        public boolean equals( Test other )
        {
            final double    epsilon = .0001;
            boolean         result  = false;
            if ( this == other )
                result = true;
            else if ( other == null )
                result = false;
            else
                result  = Math.abs( this.dnum1 - other.dnum1 ) < epsilon;
            return result;
        }

        public int hashCode()
        {
            int hash    = Double.hashCode( dnum1 );
            return hash;
        }
    }
}

I've thought about several solutions, including converting to BigDecimal, but I'm not satisfied with any of them I finally decided to round:

public boolean equals( Test other )
{
    boolean         result  = false;
    if ( this == other )
        result = true;
    else if ( other == null )
        result = false;
    else
    {
        double  test1   = round( dnum1 );
        double  test2   = round( other.dnum1 );
        result  = test1 == test2;
    }
    return result;
}

public int hashCode()
{
    double  temp    = round( dnum1 );
    int hash    = Double.hashCode( temp );
    return hash;
}

private double round( double dnum )
{
    // tests for NaN and +/-infinity omitted for brevity
    final int       places      = 4;
    final double    round_const = Math.pow( 10,places );
    double result   = ((int)(dnum * round_const + .5)) / round_const;
    return result;
}

But choosing a good rounding algorithm is difficult, and it seems expensive I looked at similar classes, such as point2d Double, but equals in this class fails, for example, when comparing. 8 with 0.799999999999999

Is there a recommended way to deal with this problem?

Solution

Answer the main questions

You don't need any custom rounding, because the double class has the doubletolongbits () method, which just converts double to long (both 64 bit values)

In addition, for the equals () method, you can compare two double values with double #compare ()

Your example might use equals () and hashcode ():

public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if (null == other
            || this.getClass() != other.getClass()) {
        return false;
    }

    return Double.compare(this.dnum1,((Test) other).dnum1) == 0;
}

public int hashCode() {
    long bits = Double.doubleToLongBits(this.dnum1);
    return (int) (bits ^ (bits >>> 32));
}

About floating point operations

Your example shows the disadvantage of the dual use of floating point calculations - even values with the same amplitude can give close but different results Maybe you should use BigDecimal?

See also the answer to this question

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>