Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8290973

In AffineTransform, equals(Object) is inconsistent with hashCode()

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 20
    • 8, 11, 17
    • client-libs
    • 2d
    • b19
    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      The equals(Object) method is inconsistent with hashCode() in the AffineTransform class. This bug prevents the use of AffineTransform as keys in HashMap, unless AffineTransform construction is well-controlled or some workaround is applied before any use as key.

      More specifically, AffineTransform breaks two contracts documented in Object.equals(Object) javadoc:

      * A.equals(A) returns false if at least one affine transform coefficient is NaN.
      * A.equals(B) should imply A.hashCode() == B.hashCode(), but it is not the case if a coefficient is zero with an opposite sign in A and B.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Following code should print "true" but prints "false":

      AffineTransform a = new AffineTransform(1, 0, 0, 1, Double.NaN, 0);
      System.out.println(a.equals(a));

      Following code should print either "true, true" or "false, <anything>" but print "true, false":

      AffineTransform a = new AffineTransform(2, 0, 0, 3, 0, +0.0);
      AffineTransform b = new AffineTransform(2, 0, 0, 3, 0, -0.0);
      System.out.println(a.equals(b));
      System.out.println(a.hashCode() == b.hashCode());


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      true
      true
      true

      or

      true
      false
      <anything>

      ACTUAL -
      false
      true
      false


      ---------- BEGIN SOURCE ----------
      import java.awt.geom.AffineTransform;

      public class Test {
          public static void main(String[] args) {
              AffineTransform r = new AffineTransform(1, 0, 0, 1, Double.NaN, 0);
              System.out.println(r.equals(r));

              AffineTransform a = new AffineTransform(2, 0, 0, 3, 0, +0.0);
              AffineTransform b = new AffineTransform(2, 0, 0, 3, 0, -0.0);
              System.out.println(a.equals(b));
              System.out.println(a.hashCode() == b.hashCode());
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Before any use of AffineTransform as a key in an HashMap:

      private static double pz(double value) {
          return (value != 0) ? value : 0;
      }

      private static void fix(AffineTransform a) {
          a.setTransform(
              pz(a.getScaleX()), pz(a.getShearY()),
              pz(s.getShearX()), pz(a.getScaleY()),
              pz(a.getTranslateX()), pz(a.getTranslateY()));
      }


      FREQUENCY : always


            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: