java - hashCode changes each time the object is created -
there escapes me hashcode. know if override equals, must override hashcode too. know if 2 objects equal, hashcode of 2 objects must equal. if fields checked in equals method don't change, hashcode should not change, right?
if so, can't understand why each time create instance of object below, different hashcode:
public class effect { private long timestamp; private int damage; private squaretype squaretype; public effect(long timestamp, int damage, squaretype squaretype) { this.timestamp = timestamp; this.damage = damage; this.squaretype = squaretype; } public long gettimestamp() { return timestamp; } public int getdamage() { return damage; } public squaretype getsquaretype() { return squaretype; } @override public boolean equals(object o) { if (this == o) return true; if (o == null || getclass() != o.getclass()) return false; effect effect = (effect) o; if (getdamage() != effect.getdamage()) return false; return getsquaretype() == effect.getsquaretype(); } @override public int hashcode() { int result = getdamage(); result = 31 * result + (getsquaretype() != null ? getsquaretype().hashcode() : 0); return result; } @override public string tostring() { string ret = "effect hashcode: " + hashcode(); return ret; } }
in code create kind of objects continuously on time. field changes each time "timestamp", 2 other fields don't change (unless there specific event). happens hashcode value different, if "damage" , "squaretype" same. don't use "timestamp" in equals , hashcode, can't understand why behavior.
update
this squaretype:
public enum squaretype { fire, wind, water, earth }
update 2
for example, if create 10 instances of effect, iterate on them , print them (tostring() returns hashcode value) 10 different values.
if 2 instances of effect have same "damage" , "squaretype" must equal , have same hashcode.
update 3
the effects created this:
@override public void friendlyfire(basebullet bullet, basesquare square) { square.notifyfriendlyfire(new effect(timeutils.millis(), square.getdamage(), square.getsquaretype()), new mykey(square.getuniqueid())); }
the effect's field changes timestamp, , don't use in equals , hashcode.
public void notifyfriendlyfire(effect neweffect, mykey key) { // system.out.println("the map contains key? " + effectmap.containskey(key)); if(effectmap.containskey(key)) { effect oldeffect = effectmap.get(key); system.out.println(neweffect); if(!oldeffect.equals(neweffect)) { system.out.println("old effect changed!"); // remove old effect removeeffect(oldeffect); // update map new effect effectmap.put(key, neweffect); // // apply new effect applyeffect(neweffect); } } else { // new effect effectmap.put(key, neweffect); applyeffect(neweffect); } }
the check "if(!oldeffect.equals(neweffect))" true, if damage , type same.
update 4
i've found bug. damage increases continuously. i've figure out why...
here's attempt @ approximating implementation:
package cruft; import java.util.date; /** * equals , hashcode test * creation date 1/16/2016. * @link https://stackoverflow.com/questions/34826585/hashcode-changes-each-time-the-object-is-created */ public class overridedemo { private long timestamp; private int damage; private squaretype squaretype; public overridedemo(int damage, squaretype squaretype) { this(damage, squaretype, new date().gettime()); } public overridedemo(int damage, squaretype squaretype, long timestamp) { if (squaretype == null) throw new illegalargumentexception("square type cannot null"); this.timestamp = timestamp; this.damage = damage; this.squaretype = squaretype; } public long gettimestamp() { return timestamp; } public int getdamage() { return damage; } public squaretype getsquaretype() { return squaretype; } @override public boolean equals(object o) { if (this == o) { return true; } if (o == null || getclass() != o.getclass()) { return false; } overridedemo = (overridedemo) o; if (damage != that.damage) { return false; } return squaretype == that.squaretype; } @override public int hashcode() { int result = damage; result = 31 * result + squaretype.hashcode(); return result; } @override public string tostring() { return "overridedemo{" + "timestamp=" + timestamp + ", damage=" + damage + ", squaretype=" + squaretype + '}'; } } enum squaretype { fire, wind, water, earth }
here's junit test shows how methods behave. tests pass; think implementation correct.
package cruft; import org.junit.assert; import org.junit.test; /** * junit test demonstrates testing equals , hashcode contract * created michael * creation date 1/16/2016. * @link https://stackoverflow.com/questions/34826585/hashcode-changes-each-time-the-object-is-created */ public class overridedemotest { @test public void testequals_null() { overridedemo x = new overridedemo(5, squaretype.earth); assert.assertfalse(x.equals(null)); } @test public void testequals_reflexive() { overridedemo x = new overridedemo(5, squaretype.earth); assert.asserttrue(x.equals(x)); } @test public void testequals_symmetric() { overridedemo x = new overridedemo(5, squaretype.earth); overridedemo y = new overridedemo(5, squaretype.earth); assert.asserttrue(x.equals(y)); assert.asserttrue(y.equals(x)); assert.asserttrue(x.hashcode() == y.hashcode()); } @test public void testequals_transitive() { overridedemo x = new overridedemo(5, squaretype.earth); overridedemo y = new overridedemo(5, squaretype.earth); overridedemo z = new overridedemo(5, squaretype.earth); assert.asserttrue(x.equals(y)); assert.asserttrue(y.equals(z)); assert.asserttrue(z.equals(x)); assert.asserttrue(x.hashcode() == y.hashcode()); assert.asserttrue(y.hashcode() == z.hashcode()); assert.asserttrue(z.hashcode() == x.hashcode()); } @test public void testequals_differentdamage_notequal() { overridedemo x = new overridedemo(5, squaretype.earth); overridedemo y = new overridedemo(10, squaretype.earth); assert.assertfalse(x.equals(y)); assert.assertfalse(y.equals(x)); assert.assertfalse(x.hashcode() == y.hashcode()); } @test public void testequals_differentsquaretype_notequal() { overridedemo x = new overridedemo(10, squaretype.earth); overridedemo y = new overridedemo(10, squaretype.fire); assert.assertfalse(x.equals(y)); assert.assertfalse(y.equals(x)); assert.assertfalse(x.hashcode() == y.hashcode()); } }
Comments
Post a Comment