Hi,
I have a class Obj. I created three objects o1,o2,03. Objects are equal if their id is equal. For example, o1 and o3 are equal. I tried adding these three objects to a HashSet, and when I print the size of the hashset I get "3" and not "2". Something is not right with the equals or hashcode method. Can someone shed some light?
code snippet:
import java.util.*;
public class Test
{
public static void main (String[] args)
{
Set hs = new HashSet();
Obj o1 = new Obj ("w", 10);
Obj o2 = new Obj ("r", 20);
Obj o3 = new Obj ("w", 30);
hs.add(o1);
hs.add(o2);
hs.add(o3);
System.out.println(hs.size());
}
public static class Obj
{
String id;
int length;
Obj (String id, int length)
{
this.id = id;
this.length = length;
}
boolean equals (Obj o)
{
if (o == null)
return false;
else if (o instanceof Obj)
return (this.id.equals(o.id));
else return false;
}
public int hashCode()
{
return id.hashCode();
}
}
}
Lew - 09 Aug 2007 13:52 GMT
> Hi,
>
[quoted text clipped - 14 lines]
> else return false;
> }
From the JLS
<http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6.5>
> If a public class has a method or constructor with default access, then this method or constructor is not accessible to or inherited by a subclass declared outside this package.
You didn't override equals().

Signature
Lew
lowenbrau - 09 Aug 2007 14:22 GMT
>> Hi,
>> I have a class Obj. I created three objects o1,o2,03. Objects are equal
[quoted text clipped - 18 lines]
>
> You didn't override equals().
default access?
I don't have a subclass? or any package?
Can you be help some more?
Thomas Fritsch - 09 Aug 2007 14:33 GMT
>>>If a public class has a method or constructor with default access, then
>>>this method or constructor is not accessible to or inherited by a
[quoted text clipped - 3 lines]
>
> default access?
He means: If the overridden method is public (in your case:
equals(Object) of class java.lang.Object), then the overriding method
(in your case: equals(Object) of your class Obj) must be public too.
Doing not so will cause the compiler to complain.
> I don't have a subclass? or any package?
You *have* a subclass: Your class Obj is a subclass of java.lang.Object.
You also *have* a package (the name-less default package), which is
different from the package "java.lang".
> Can you be help some more?

Signature
Thomas
Patricia Shanahan - 09 Aug 2007 14:33 GMT
>>> Hi,
>>> I have a class Obj. I created three objects o1,o2,03. Objects are equal
[quoted text clipped - 20 lines]
> I don't have a subclass? or any package?
> Can you be help some more?
The equals method in Object is declared "public boolean equals(Object obj)"
To override it, you must declare an equals with the same signature. The
only thing you can safely change is the identifier for the parameter:
public boolean equals(Object o)
is fine. Changing anything else will prevent your method from overriding
the Object equals.
Note that when testing an equals implementation it is important to
include tests where the parameter has type Object, even if it references
an instance of your class:
Test someTest = new Test...
Object o1 = someTest;
and use o1 as the equals parameter. That is how it will be used, in
effect, in java.util collections.
[If it were "public boolean equals(SomeClass obj)" you could replace
"SomeClass" with a superclass or super-interface. Object has no
superclasses, so that is not an option for equals.]
Patricia
Thomas Fritsch - 09 Aug 2007 14:08 GMT
lowenbrau schrieb:
> Something is not right with the equals or hashcode method. Can someone shed some light?
[...]
> boolean equals (Obj o)
In order to override
equals(Object o)
you have to declare it as
equals(Object o)
and not
equals(Obj o)
> {
>
[quoted text clipped - 4 lines]
> else return false;
> }

Signature
Thomas
lowenbrau - 09 Aug 2007 14:24 GMT
> lowenbrau schrieb:
>> Something is not right with the equals or hashcode method. Can someone
[quoted text clipped - 13 lines]
>> return (this.id.equals(o.id));
>> else return false; }
Thankyou!
Roedy Green - 10 Aug 2007 04:11 GMT
> boolean equals (Obj o)
when you override you must exactly match the signature of the beast in
base class. equals should be public.
I have not experimented with the @override annotation to make sure it
generates an error message if my signature does not exactly match
something in the base class.

Signature
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
Roedy Green - 10 Aug 2007 04:21 GMT
The signature must exactly match:
public boolean equals( Object o )
not
boolean equals( Obj o )
Unfortunately you won't get an error message. Javac does not know you
are trying to override equals. It thinks you are making up an
overloaded variant.
>if (o == null)
> return false;
> else if (o instanceof Obj)
> return (this.id.equals(o.id));
> else return false;
If you ever fed that to IntelliJ likely it would ask if you wanted it
converted to:
return o != null && o instanceof Obj && this.id.equals(o.id);
What does instanceof do with nulls?

Signature
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
Roedy Green - 10 Aug 2007 04:28 GMT
On Fri, 10 Aug 2007 03:21:29 GMT, Roedy Green
<see_website@mindprod.com.invalid> wrote, quoted or indirectly quoted
someone who said :
> return o != null && o instanceof Obj && this.id.equals(o.id);
>What does instanceof do with nulls?
null instanceof SomeClass is always false.
Therefore you can collapse that expression to:
return o instanceof Obj && this.id.equals(o.id);
The way you wrote your code, o HAD to be an Obj so the instanceof was
nugatory.
Had you written the code correctly, there could be some doubt.
e.g.
public boolean equals (Object o)
{
return o instanceof Obj && this.id.equals(((Obj)o).id);
}

Signature
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com