Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4459681
Votes 0
Synopsis HashSet.contains DOCUMENTATION, et. al. not precise
Category java:classes_util
Reported Against ladybird-rc2
Release Fixed
State 11-Closed, Not a Defect, bug
Priority: 4-Low
Related Bugs
Submit Date 16-MAY-2001
Description




java version "1.3.1-rc2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-rc2-b23)
Java HotSpot(TM) Client VM (build 1.3.1-rc2-b23, mixed mode)

The documentation for HashSet, et al, is not precise enough.

For instance,

HashSet.contains(Object o) says:
"Returns true if this set contains the specified element.
Specified by:
   contains in interface Set"

As this is a relatively abstract description, one reads Set.contains which says:
"...More formally, returns true if and only if this set contains an element e
such that ((o == null) ? (e == null) : o.equals(e))"

But this is not true, If two elements of a HashSet do not map to the same
bucket equals is never called.

Documentation for HashSet.contains(Object o) et al, should be embellished to
say:
"Returns true if this set contains the specified element. More formally,
returns true if and only if this set contains an element e such that e.hashCode
() == o.hashCode(), and ((o == null) ? (e == null) : o.equals(e))"
-----------------------------------------------------------------------

Here is a sample program exhibiting the difference. As is, contains will return
false. If you uncomment the hashCode function, contains will return true.

import java.util.*;

public class ContainsDoc
{
    public static void main( String[] args )
    {
        HashSet hs = new HashSet();
        
        Data d1 = new Data( "Hello" );
        Data d2 = new Data( "Hello" );
        
        hs.add( d1 );
        if (hs.contains( d2 ))
            System.out.println("Found d2");
        else
            System.out.println("Did not find d2");
        System.exit(0);
    }
}

class Data
{
    String m_Info;
    
    public Data( String info )
    {
        m_Info = info;
    }
    
    public boolean equals( Object o )
    {
        System.out.println("Equals called on " + toString() );
        if (o instanceof Data)
        {
            return m_Info.equals( ((Data) o).m_Info );
        }
        
        return false;
    }
    
/*
    public int hashCode()
    {
        return m_Info.hashCode();
    }
 */
}
(Review ID: 124507) 
======================================================================
Work Around




Use hashCode(). There is nothing wrong with the JRE. The documentation is just
not precise enough.
======================================================================
Evaluation
If two elements do not map to the same bucket, then their hashcodes are unequal, and as per the contract between hashcode and equals, two items are not equal if their hashcodes are not equal. It would be redundant to check the equality of two elements that do not have the same hashcode. Similiarly no check for the equality of hashcodes is needed since if two elements are equal they must have the same hashcode.
  xxxxx@xxxxx   2001-05-16
Comments
  
  Include a link with my name & email   

Submitted On 25-MAY-2001
dmbdmb
I agree with the evaluation, My point is the documentation 
doesn't clearly explain this. All I want is for the doc to 
read:

"Returns true if this set contains the specified element. 
More formally,
returns true if and only if this set contains an element e 
such that e.hashCode
() == o.hashCode(), and ((o == null) ? (e == null) : 
o.equals(e))"


Submitted On 11-NOV-2001
mpopesun
You have no idea the 100,000's of programmers who have wasted hours each debugging this horrible 
documentation and implementation bug.  Both in HashSet, and in TreeSet, it is stated that equals(obj) is 
called on the elements, which would call the programmers' defined equals(..) method to exhibit well-defined 
equality behaviour.  Whoever wrote that comment 'nothing is wrong with the JRE' should be fired.


Submitted On 22-FEB-2002
mitalub
The documentation leads one to believe that .equals is used 
in determining if the object is in the Set, as with 
ArrayList.  This documentation should make it clear that 
the hashcodes are what is used.


Submitted On 19-JUN-2002
jswann
Seriously, how much effort would it take to FIX THE DOCUMENTATION?

Refusing to do so seems pretty uncooperative -- and out of character.


Submitted On 06-JUN-2003
deckm
Add my name to the list of the 100,000's who have wasted
hours. The documentation in 1.4.1 still says "returns true
if and only if this set contains an element e such that
(o==null ? e==null : o.equals(e))" which certainly implied
to me that you're doing the equals operation on the element
and not on the element's hashcode. Several hours later,
after realizing that it works right if I use another
container like Vector, I got the idea to check the bug
parade. It's outrageous to argue that this neither a code
bug nor a doc bug!  


Submitted On 17-OCT-2003
jpaulkeller
I agree with above comments.  Please fix the docs!  I just 
wasted a day with essentially the same problem (in TreeSet).


Submitted On 08-MAY-2004
Trakisko
The documentation still hasn't been clarified as of 
version 1.4.2.  It should be.  One shouldn't have to 
consult the BugParade to find out how this method 
really works.


Submitted On 22-MAY-2007
xerces8
JDK 1.5.0 , no change...


Submitted On 23-MAY-2007
virgo47
Yup, I completely agree. Sun is quite stubborn (and not right) with few bugs and this is one of them.

Of course... Java SE 6 still the same.


Submitted On 21-NOV-2007
DAMN.. i just spent an entire hour debugging this crap.. IMHO, fixing the documentation isn't an option.. The implementation is wrong. The Set interface clearly says "o.equals(e)".. nothing about hashCode()...  Simply changing the documentation does not fix the problem.  It's an interface. Respect it.  



PLEASE NOTE: JDK6 is formerly known as Project Mustang