You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by Age Mooy <am...@home.nl> on 2001/09/27 16:20:18 UTC

[PATCH] Missing hashCode() method in Criteria.Criterion (Turbine-2)

Hi,

I was trying to store query results in the global cache service using a key based on the hashcode of the
Criteria object and I found out that hashcodes for equal Criteria are not equal. This breaks the rules because
the Java spec says something like this:

"If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of
the two objects must produce the same integer result"

This problem occurs because the Criteria.Criterion inner class defines an equals() method without defining a
matching hashCode() method.

I played around a bit and came up with this implementation:

/**
 * Returns a hash code value for the object.
 */
public int hashCode()
{
    int h = value.hashCode() + comparison.hashCode();

    if (table != null)
      h += table.hashCode();

    if (column != null)
      h += column.hashCode();

    if (and != null)
      h += and.hashCode();

    if (or != null)
      h += or.hashCode();

    return h;
}

I'm no hashCode expert but it works consistently with my tests.

The patch for the above code (in jakarta-turbine-2) is attached below,
Age


Index: src/java/org/apache/turbine/util/db/Criteria.java
===================================================================
RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Criteria.java
--- src/java/org/apache/turbine/util/db/Criteria.java	2001/08/16 05:09:46	1.1.1.1
+++ src/java/org/apache/turbine/util/db/Criteria.java	2001/09/27 14:11:14
@@ -3650,6 +3650,28 @@
             return isEquiv;
         }

+        /**
+         * Returns a hash code value for the object.
+         */
+        public int hashCode()
+        {
+            int h = value.hashCode() + comparison.hashCode();
+
+            if (table != null)
+              h += table.hashCode();
+
+            if (column != null)
+              h += column.hashCode();
+
+            if (and != null)
+              h += and.hashCode();
+
+            if (or != null)
+              h += or.hashCode();
+
+            return h;
+        }
+
         public String[] getAllTables()
         {
             StringStackBuffer tables = new StringStackBuffer();



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: [PATCH] Missing hashCode() method in Criteria.Criterion (Turbine-2)

Posted by John McNally <jm...@collab.net>.
Sorry, you were right there is no problem overflowing an int.  Wish I
would have known that when writing some other hashCode methods.  Thanks
for adding the braces.

john mcnally

Age Mooy wrote:
> 
> Hmmm... I looked at the implementations of Hashtable and AbstractSet and both of them use this int addition
> scheme. I'm a little rusty on what happens when the number gets too big for an int but I did get some negative
> numbers in my tests. I could cast the whole lot to longs ?
> The only other method I've found while browsing through jdk source code is the bitwise XOR operator... would
> that be sufficient ? Do you have another suggestion ?
> 
> The patch for that last one (incl. fancy brackets) would be:
> 
> Index: src/java/org/apache/turbine/util/db/Criteria.java
> ===================================================================
> RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 Criteria.java
> --- src/java/org/apache/turbine/util/db/Criteria.java   2001/08/16 05:09:46     1.1.1.1
> +++ src/java/org/apache/turbine/util/db/Criteria.java   2001/09/27 22:29:07
> @@ -3650,6 +3650,36 @@
>              return isEquiv;
>          }
> 
> +        /**
> +         * Returns a hash code value for the object.
> +         */
> +        public int hashCode()
> +        {
> +            int h = value.hashCode() ^ comparison.hashCode();
> +
> +            if (table != null)
> +            {
> +              h ^= table.hashCode();
> +            }
> +
> +            if (column != null)
> +            {
> +              h ^= column.hashCode();
> +            }
> +
> +            if (and != null)
> +            {
> +              h ^= and.hashCode();
> +            }
> +
> +            if (or != null)
> +            {
> +              h ^= or.hashCode();
> +            }
> +
> +            return h;
> +        }
> +
>          public String[] getAllTables()
>          {
>              StringStackBuffer tables = new StringStackBuffer();
> 
> Age
> 
> > I think you need to be more careful of overflows.
> >
> > john mcnally
> >
> > Age Mooy wrote:
> > >
> > > Hi,
> > >
> > > I was trying to store query results in the global cache service using a key based on the hashcode of the
> > > Criteria object and I found out that hashcodes for equal Criteria are not equal. This breaks the
> > rules because
> > > the Java spec says something like this:
> > >
> > > "If two objects are equal according to the equals(Object) method, then calling the hashCode
> > method on each of
> > > the two objects must produce the same integer result"
> > >
> > > This problem occurs because the Criteria.Criterion inner class defines an equals() method without
> > defining a
> > > matching hashCode() method.
> > >
> > > I played around a bit and came up with this implementation:
> > >
> > > /**
> > >  * Returns a hash code value for the object.
> > >  */
> > > public int hashCode()
> > > {
> > >     int h = value.hashCode() + comparison.hashCode();
> > >
> > >     if (table != null)
> > >       h += table.hashCode();
> > >
> > >     if (column != null)
> > >       h += column.hashCode();
> > >
> > >     if (and != null)
> > >       h += and.hashCode();
> > >
> > >     if (or != null)
> > >       h += or.hashCode();
> > >
> > >     return h;
> > > }
> > >
> > > I'm no hashCode expert but it works consistently with my tests.
> > >
> > > The patch for the above code (in jakarta-turbine-2) is attached below,
> > > Age
> > >
> > > Index: src/java/org/apache/turbine/util/db/Criteria.java
> > > ===================================================================
> > > RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
> > > retrieving revision 1.1.1.1
> > > diff -u -r1.1.1.1 Criteria.java
> > > --- src/java/org/apache/turbine/util/db/Criteria.java   2001/08/16 05:09:46     1.1.1.1
> > > +++ src/java/org/apache/turbine/util/db/Criteria.java   2001/09/27 14:11:14
> > > @@ -3650,6 +3650,28 @@
> > >              return isEquiv;
> > >          }
> > >
> > > +        /**
> > > +         * Returns a hash code value for the object.
> > > +         */
> > > +        public int hashCode()
> > > +        {
> > > +            int h = value.hashCode() + comparison.hashCode();
> > > +
> > > +            if (table != null)
> > > +              h += table.hashCode();
> > > +
> > > +            if (column != null)
> > > +              h += column.hashCode();
> > > +
> > > +            if (and != null)
> > > +              h += and.hashCode();
> > > +
> > > +            if (or != null)
> > > +              h += or.hashCode();
> > > +
> > > +            return h;
> > > +        }
> > > +
> > >          public String[] getAllTables()
> > >          {
> > >              StringStackBuffer tables = new StringStackBuffer();
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


RE: [PATCH] Missing hashCode() method in Criteria.Criterion (Turbine-2)

Posted by Age Mooy <am...@home.nl>.
Hmmm... I looked at the implementations of Hashtable and AbstractSet and both of them use this int addition
scheme. I'm a little rusty on what happens when the number gets too big for an int but I did get some negative
numbers in my tests. I could cast the whole lot to longs ?
The only other method I've found while browsing through jdk source code is the bitwise XOR operator... would
that be sufficient ? Do you have another suggestion ?

The patch for that last one (incl. fancy brackets) would be:

Index: src/java/org/apache/turbine/util/db/Criteria.java
===================================================================
RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Criteria.java
--- src/java/org/apache/turbine/util/db/Criteria.java	2001/08/16 05:09:46	1.1.1.1
+++ src/java/org/apache/turbine/util/db/Criteria.java	2001/09/27 22:29:07
@@ -3650,6 +3650,36 @@
             return isEquiv;
         }

+        /**
+         * Returns a hash code value for the object.
+         */
+        public int hashCode()
+        {
+            int h = value.hashCode() ^ comparison.hashCode();
+
+            if (table != null)
+            {
+              h ^= table.hashCode();
+            }
+
+            if (column != null)
+            {
+              h ^= column.hashCode();
+            }
+
+            if (and != null)
+            {
+              h ^= and.hashCode();
+            }
+
+            if (or != null)
+            {
+              h ^= or.hashCode();
+            }
+
+            return h;
+        }
+
         public String[] getAllTables()
         {
             StringStackBuffer tables = new StringStackBuffer();


Age


> I think you need to be more careful of overflows.
>
> john mcnally
>
> Age Mooy wrote:
> >
> > Hi,
> >
> > I was trying to store query results in the global cache service using a key based on the hashcode of the
> > Criteria object and I found out that hashcodes for equal Criteria are not equal. This breaks the
> rules because
> > the Java spec says something like this:
> >
> > "If two objects are equal according to the equals(Object) method, then calling the hashCode
> method on each of
> > the two objects must produce the same integer result"
> >
> > This problem occurs because the Criteria.Criterion inner class defines an equals() method without
> defining a
> > matching hashCode() method.
> >
> > I played around a bit and came up with this implementation:
> >
> > /**
> >  * Returns a hash code value for the object.
> >  */
> > public int hashCode()
> > {
> >     int h = value.hashCode() + comparison.hashCode();
> >
> >     if (table != null)
> >       h += table.hashCode();
> >
> >     if (column != null)
> >       h += column.hashCode();
> >
> >     if (and != null)
> >       h += and.hashCode();
> >
> >     if (or != null)
> >       h += or.hashCode();
> >
> >     return h;
> > }
> >
> > I'm no hashCode expert but it works consistently with my tests.
> >
> > The patch for the above code (in jakarta-turbine-2) is attached below,
> > Age
> >
> > Index: src/java/org/apache/turbine/util/db/Criteria.java
> > ===================================================================
> > RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
> > retrieving revision 1.1.1.1
> > diff -u -r1.1.1.1 Criteria.java
> > --- src/java/org/apache/turbine/util/db/Criteria.java   2001/08/16 05:09:46     1.1.1.1
> > +++ src/java/org/apache/turbine/util/db/Criteria.java   2001/09/27 14:11:14
> > @@ -3650,6 +3650,28 @@
> >              return isEquiv;
> >          }
> >
> > +        /**
> > +         * Returns a hash code value for the object.
> > +         */
> > +        public int hashCode()
> > +        {
> > +            int h = value.hashCode() + comparison.hashCode();
> > +
> > +            if (table != null)
> > +              h += table.hashCode();
> > +
> > +            if (column != null)
> > +              h += column.hashCode();
> > +
> > +            if (and != null)
> > +              h += and.hashCode();
> > +
> > +            if (or != null)
> > +              h += or.hashCode();
> > +
> > +            return h;
> > +        }
> > +
> >          public String[] getAllTables()
> >          {
> >              StringStackBuffer tables = new StringStackBuffer();
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: [PATCH] Missing hashCode() method in Criteria.Criterion (Turbine-2)

Posted by John McNally <jm...@collab.net>.
I think you need to be more careful of overflows.

john mcnally

Age Mooy wrote:
> 
> Hi,
> 
> I was trying to store query results in the global cache service using a key based on the hashcode of the
> Criteria object and I found out that hashcodes for equal Criteria are not equal. This breaks the rules because
> the Java spec says something like this:
> 
> "If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of
> the two objects must produce the same integer result"
> 
> This problem occurs because the Criteria.Criterion inner class defines an equals() method without defining a
> matching hashCode() method.
> 
> I played around a bit and came up with this implementation:
> 
> /**
>  * Returns a hash code value for the object.
>  */
> public int hashCode()
> {
>     int h = value.hashCode() + comparison.hashCode();
> 
>     if (table != null)
>       h += table.hashCode();
> 
>     if (column != null)
>       h += column.hashCode();
> 
>     if (and != null)
>       h += and.hashCode();
> 
>     if (or != null)
>       h += or.hashCode();
> 
>     return h;
> }
> 
> I'm no hashCode expert but it works consistently with my tests.
> 
> The patch for the above code (in jakarta-turbine-2) is attached below,
> Age
> 
> Index: src/java/org/apache/turbine/util/db/Criteria.java
> ===================================================================
> RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 Criteria.java
> --- src/java/org/apache/turbine/util/db/Criteria.java   2001/08/16 05:09:46     1.1.1.1
> +++ src/java/org/apache/turbine/util/db/Criteria.java   2001/09/27 14:11:14
> @@ -3650,6 +3650,28 @@
>              return isEquiv;
>          }
> 
> +        /**
> +         * Returns a hash code value for the object.
> +         */
> +        public int hashCode()
> +        {
> +            int h = value.hashCode() + comparison.hashCode();
> +
> +            if (table != null)
> +              h += table.hashCode();
> +
> +            if (column != null)
> +              h += column.hashCode();
> +
> +            if (and != null)
> +              h += and.hashCode();
> +
> +            if (or != null)
> +              h += or.hashCode();
> +
> +            return h;
> +        }
> +
>          public String[] getAllTables()
>          {
>              StringStackBuffer tables = new StringStackBuffer();
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: [PATCH] Missing hashCode() method in Criteria.Criterion (Turbine-2)

Posted by John McNally <jm...@collab.net>.
Also please follow coding guidelines when sending patches.  (Braces)

john mcnally

Age Mooy wrote:
> 
> Hi,
> 
> I was trying to store query results in the global cache service using a key based on the hashcode of the
> Criteria object and I found out that hashcodes for equal Criteria are not equal. This breaks the rules because
> the Java spec says something like this:
> 
> "If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of
> the two objects must produce the same integer result"
> 
> This problem occurs because the Criteria.Criterion inner class defines an equals() method without defining a
> matching hashCode() method.
> 
> I played around a bit and came up with this implementation:
> 
> /**
>  * Returns a hash code value for the object.
>  */
> public int hashCode()
> {
>     int h = value.hashCode() + comparison.hashCode();
> 
>     if (table != null)
>       h += table.hashCode();
> 
>     if (column != null)
>       h += column.hashCode();
> 
>     if (and != null)
>       h += and.hashCode();
> 
>     if (or != null)
>       h += or.hashCode();
> 
>     return h;
> }
> 
> I'm no hashCode expert but it works consistently with my tests.
> 
> The patch for the above code (in jakarta-turbine-2) is attached below,
> Age
> 
> Index: src/java/org/apache/turbine/util/db/Criteria.java
> ===================================================================
> RCS file: /home/cvspublic/jakarta-turbine-2/src/java/org/apache/turbine/util/db/Criteria.java,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 Criteria.java
> --- src/java/org/apache/turbine/util/db/Criteria.java   2001/08/16 05:09:46     1.1.1.1
> +++ src/java/org/apache/turbine/util/db/Criteria.java   2001/09/27 14:11:14
> @@ -3650,6 +3650,28 @@
>              return isEquiv;
>          }
> 
> +        /**
> +         * Returns a hash code value for the object.
> +         */
> +        public int hashCode()
> +        {
> +            int h = value.hashCode() + comparison.hashCode();
> +
> +            if (table != null)
> +              h += table.hashCode();
> +
> +            if (column != null)
> +              h += column.hashCode();
> +
> +            if (and != null)
> +              h += and.hashCode();
> +
> +            if (or != null)
> +              h += or.hashCode();
> +
> +            return h;
> +        }
> +
>          public String[] getAllTables()
>          {
>              StringStackBuffer tables = new StringStackBuffer();
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org