Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: hashCode idea

  1. #1
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default hashCode idea

    Hi,
    I was reading about the need to implement both equals() and hashCode() at
    Java theory and practice: Hashing it out

    and so I want to ask what y'all think of this hashCode() idea. I am looking at an object with 25 data members that I have coded an equals() for, and frankly, unique hashCodes in an int don't seem possible.

    How about providing a hashCode int in a given class, also with a static class member which is how high the numbering has gone?

    And then add to that the ability to put 20 variables into a single String and perform string comparisons instead of using an int?

    Java Code:
    class foo {
        static int nextHashIndex = 1;
        private int hashCode = 0;
        private String hashString = null;
    
        public int hashCode() {
            if(hashCode == 0)
                setHashCode();
            return hashCode;
        }
    
        public String hashString() { 
            if(hashString == null)
                setHashCode();
            return hashString; 
        }
    
        private static int getNextHashIndex() { return nextHashIndex++; }
    
        private void setHashCode() {
            hashCode = getNextHashIndex();
            hashString = "convoluted method for putting the hashString together";
        }
    
        public boolean equals(Object o) {
            if(hashCode == 0)
                setHashCode();
            return o.hashString().equals(hashString);
        }
    }
    Which would facilitate equals, hashCode, and compare, for large objects. The hashCode() int would be precise, when working with a class that is not instantiated more than a few billion times.

    Would you think this a good approach to dealing with equals, hashCode and compare? For compare, it would be string compare, and one would start with most significant data members to least, I suppose, in building the hashString.

    TIA, and cheers,
    Mark

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    26

    Default

    Sorry but that seems a bad idea. The hashCode should vary as equals varies. If two objects are equal via your equals method, then they must return the same hashCode (the converse is not necessarily true).

  3. #3
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Sorry, that was the first stream of consciousness.

    The hashString has to be looked up in existing hash strings, which would have to be kept, returning the hash code for the matching string or a new hash code, so hash code comparisons would work (without strings).

    Other question: If equals() works OK, and I do not call hashCode(), do I need to implement hashCode()?

    TIA, and cheers,
    Mark
    Last edited by Markgm; 08-14-2011 at 02:30 AM.

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    It depends on how you are using the classes. If you don't need other classes to hold and sort your class, then it doesn't matter. If you are using the collection framework classes then you need to follow the rules.

  5. #5
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Hi,
    Here is the way it would work using unique hashCodes for up to a couple billion instances of a class with a complex set of data elements.
    There is no provision here for removing strings from the static ArrayList such as when objects are destroyed, which would make it more complete.

    Java Code:
    class foo {
    	private static int nextHashIndex = 1;
    	private static ArrayList<String> hashStrings = new ArrayList<String>();
    	
    	private int hashCode = 0;
    	private String hashString = null;
    	
    	private static int getHashCode(String s) {
    		int h = hashStrings.indexOf(s);
    		if(h == 0) {
    			hashStrings.add(s);
    			h = nextHashIndex++;
    		}
    		return h; 
    	}
    	
    	public int hashCode() {
    		if(hashCode == 0)
    			hashCode = getHashCode(hashString());
    		return hashCode;
    	}
    	
    	private String hashString() {
    		if(hashString == null) {
    			// create complex hash string
    		} 
    		return hashString;
    	}
    }

  6. #6
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    As long as:
    If two objects are equal via your equals method, then they must return the same hashCode

  7. #7
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Well, if I don't override hashCode(), but I do override equals(), and I think that if my equals() says equal, then the contents of the two will be the same. I believe that will cause any underlying hashCode() call to return equal hash codes?

    I am also just realizing, when the foo type above - when the object changes, it will have to do its hash string and code anew. But that is the basic idea - to use an int as an index into a more complete hash code.
    Last edited by Markgm; 08-14-2011 at 02:56 AM.

  8. #8
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    Make a test class, create some instances and put them into a HashMap and see what happens.
    Do you understand how hash values are used? The collection uses the hash code to select which bucket to put an object in. A bucket can contain more than one object. Its a way of mapping large index to a smaller space.
    For example say your index can have 100 million different values(0-100000000), but your data has only 10 thousand different values with indexes randomly spaced in that 100 million range. You want a way to store those 10 thousand values in an 1000 lists of 10 items each. When you want to retrieve an item using its index in the 100 million range, you need a way to convert it to an index in the 1000 range to select one of the 1000 lists to search for the item using the equals method. If the hash is the same, then you have a list of 10 to search.
    The mapping of the index from 100 million to 10 thousand is done by hashing.
    Given this, can you see why hash and equals must give correlating values.

  9. #9
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    I do not know how hashCodes are used by the Object class, for example, which is what I am inheriting from. I have a class with a need to compare using equals(), and over 20 member variables are being compared in it. I'm not sure how well I could make a useful representation of that in a hashCode, or what it would be used for.

    Add: These are the members. 3 strings, 11 booleans, 1 short[5-10] boolean array, 5 ints, and 3 mutable refs (each contains 1 boolean, 2 enums and 2 ints).
    Last edited by Markgm; 08-14-2011 at 03:38 AM.

  10. #10
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    what it would be used for
    What containers are you putting your class objects in? Do they use the object's hashcode?

  11. #11
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    If I said that the hash codes I make were relatively meaningless, but always met the requirement that equal value gives an equal hash code, would that meet all of the necessary requirements?

  12. #12
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Quote Originally Posted by Norm View Post
    What containers are you putting your class objects in? Do they use the object's hashcode?
    Just class MyClass (inheriting from Object). I coded it all, and I have not used a hashCode() or an equals() on it. Like foo, but with a couple dozen data members and many lines of member functions.
    Last edited by Markgm; 08-14-2011 at 03:50 AM.

  13. #13
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    If two objects are equal with your method and by your hashcode method they will have the same hashcode.
    That should work. The classes that use hashcode to select a bucket for an object would be looking in the correct bucket where it could expect to get an equal match. There would be no other buckets where there would be an object that would be equal to the object being placed/searched for.

  14. #14
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    What containers are you putting your MyClass objects in?

  15. #15
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Quote Originally Posted by Norm View Post
    What containers are you putting your MyClass objects in?
    I have no idea. I am using the eclipse IDE, and they are not coded to extend anything, in the IDE dialog (create class) it defaulted to Object.

  16. #16
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    SW Missouri
    Posts
    17,308
    Rep Power
    25

    Default

    By container I was referring to ArrayList, Map, List, Set, etc. A class the you add your MyClass objects to.
    They are the classes that will require the equals and hashcode methods to return the right values.

  17. #17
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    OK. I like to use ArrayList in many places, but I have no look-up kind of activity going on in any container of my objects. The only calls to equals() I am considering are for if there has been a change in one of 20+ different settings while the user is interacting with a view to those (model) settings. So I need an equals() that gives a very precise response of equals or not between current and previous instances of the whole content.

  18. #18
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    From discussion
    java - Should mutable collections override equals and hashCode? - Stack Overflow
    You should not override equals and hashCode so that they reflect the mutable member.

    There are two reasons:

    first: because this would break the contract of hash code:

    Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer...
    @see: JavaDoc Object#hashCode()

    second: technical vs. business logic

    If you break that requirement HashSet and HashMap and every component based on them will probaly not work correct.

    The second reason not to do this: is more my personal point of view. I think hash code and equals are technical terms that should not be used to implement business logic. Imagine: you have two Objects (not only Collections) and ask if they are equals, then there are two different ways to answer them:

    technical: the are equals if they represent the same object, which is different from being the same object (if you think of proxies, serilization, remote stuff...)
    bussines logic: they are equals if the look the same (same attribute) – the important thing here is, that there is not the holy one definition of equality even to the same class in even one application. (Sample question: when are two stones equals?))

    But because equals is used by technical stuff (HashMap), you should implement it in a technical way, and build the business logic related equals by something else (something like the comparator interface). And for your collection it means: do not override equals and hashCode (in a way that breaks the technical contract).
    So I suppose another possibility is to avoid equals() for my 'business' purposes. . But Comparator has an equals() method, so how do I avoid overridin the Object equals()?

    - Mark

  19. #19
    Markgm is offline Member
    Join Date
    Nov 2010
    Location
    VT, USA
    Posts
    31
    Rep Power
    0

    Default

    Java Code:
    // the Str class
    public class Str {
    	private String s = null;
    	public Str(String t) { s = t; }
    	public String string() { return s; }
    	public void setString(String t) { s = t; }
    	
    	public boolean equals(Object o) {
    		Str str = (Str) o;
    		if(str == this) {
    			System.out.println("Str.equals() str == this");
    			return true;
    		}
    		if(str.string() == this.s) {
    			System.out.println("Str.equals() str.string() == this.s");
    			return true;
    		}
    		return false;
    	}
    }
    // ------------------------------------------------------
    
    				// goof - snippet from main()
    				
    		String s = "hello", t = "hello";
    		if(s == t)
    			System.out.println("s == t");
    		if(s.equals(t))
    			System.out.println("s.equals(t)");
    		
    		Str s1 = new Str("hello");
    		Str s2 = new Str("hello");
    		if(s1 == s2)
    			System.out.println("s1 == s2");
    		if(s1.equals(s2))
    			System.out.println("s1.equals(s2)");
    		if(s1.equals(s1))
    			System.out.println("s1.equals(s1)"); 
    		
    		Object o1 = new Object(), o2 = new Object();
    		if(o1 == o2)
    			System.out.println("o1 == o2");
    		if(o1.equals(o2))
    			System.out.println("o1.equals(o2)");
    		System.out.println("o1 hash: "+o1.hashCode()+", o2 hash: "+o2.hashCode());
    Java Code:
     Output:
    s == t
    s.equals(t)
    Str.equals() str.string() == this.s
    s1.equals(s2)
    Str.equals() str == this
    s1.equals(s1)
    o1 hash: 1140995926, o2 hash: 1837044219
    The above, with two of type Object that do not come out as equals(). Also of note, prior to coding equals() in class Str, s1 and s2 did not come out equals. Seeing this, I might like to resolve to not implement equals() in order to do full content comparisons, but rather, to implement my own interface - ContentEquals, with one entrypoint - contentEquals(), to do these kinds of comparisons, and not get caught up in the way Object uses equals() and hashCode(). Moving on further...

    From Object (Java Platform SE 6)
    Under hashCode:

    The general contract of hashCode is: ...
    Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. ...
    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. ...
    It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables. ...

    Under equals:

    The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

    Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
    The text above under equals() makes it sound like all that equals() does with mutable objects is tell you if the references are to the same object. but not if the content of two objects are equal.

    Perhaps I am now also seeing how these two have to be used. A person must do both (to do one) to maintain all of the contracts. If one overrides equals(), then one really needs to override hashCode() so that they are in synch with each other (and can maintain the above contracts). Although, if I understand how equals() is described above, it uses the reference itself (x or y) as part of what has to be equals? So in class Object, the hashCode is basically the object address, which is a part of being "totally equals". That is too equals for me. I want to have two separate objects that can come out true on equals, by having the same content. So, the basic type Object is only equals if it has the same address, i.e. hashCode. Inheriting from Object, which everything does, can add its own checks for the data members it adds. Or, perhaps in one's equals() implementations, one could skip the basic address hashCoding of Object and just do the derived content, for both the hashCode() and the equals().

    Looking at the fine print, the hashCode() can change during execution, when the data used in making the hashCode changes, so the hash code does not have to stay the same during its lifetime. I can always generate hash codes and results for equals() as the current time, so long as they are on the same page with each other (and the contracts above). I might get a performance improvement from more unique hash codes. I do not see a negative to having a hash code that changes however many times during an object's lifetime (beyond the processing required to generate the code).

    Other than that, I suppose hashCode() and equals() may get ugly with inheritance... Having to use base class members but add to them. If I make class Derived from class Base, (where I suppose Base is derived from Object), how do I call into the Base equals() and hashCode() from the derived ones?
    Last edited by Markgm; 08-14-2011 at 11:05 AM.

  20. #20
    DarrylBurke's Avatar
    DarrylBurke is offline Member
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,193
    Rep Power
    19

Page 1 of 2 12 LastLast

Similar Threads

  1. Hashcode definition question!!
    By chathura87 in forum New To Java
    Replies: 8
    Last Post: 03-03-2011, 03:28 PM
  2. equals() and HashCode()
    By jomypgeorge in forum New To Java
    Replies: 1
    Last Post: 02-10-2011, 07:34 AM
  3. hashCode() contract
    By jomypgeorge in forum New To Java
    Replies: 3
    Last Post: 01-14-2011, 11:32 AM
  4. hashCode questions
    By alpdog14 in forum New To Java
    Replies: 3
    Last Post: 02-19-2010, 11:00 PM
  5. An acceptable hashcode?
    By dsym@comcast.net in forum New To Java
    Replies: 7
    Last Post: 03-29-2009, 09:04 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •