Reputation: 13
so I have a small issue that I cant wrap my head around.
I have a need to store a class object as a key in a map and for it to be retrieved later by a newly created object looking against the map. I have a class that implements Cloneable
and overrides toString
, hashCode
and equals
, but it seems that the object is unique and no matter how I create the object to use as a key to retrieve the value from the map, the new object that should match the key, doesn't.
package com.keneti.tekkit.objects;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import com.keneti.main.KenetiPrereq;
/** Simple object representing an block by the ID:DATA.
*
* @author Michael Mason */
public class SimpleBlock implements Cloneable {
protected final int id;
protected byte data;
/** Creates a new SimpleBlock object with a data value of zero.
*
* @param id The Block ID. */
public SimpleBlock(int id) {
this.id = id;
this.data = 0;
}
/** Creates a new SimpleBlock object.
*
* @param id The Block ID.
* @param data The block data to set. */
public SimpleBlock(int id, byte data) {
this.id = id;
this.data = data;
}
/** Creates a new SimpleBlock object from a {@link Block}.
*
* @param block A bukkit block. */
public SimpleBlock(Block block) {
this(block.getTypeId(), block.getData());
}
/** Creates a new SimpleBlock object from an {@link ItemStack}.
*
* @param itemStack A bukkit ItemStack. */
public SimpleBlock(ItemStack itemStack) {
this(itemStack.getTypeId(), itemStack.getData().getData());
}
/** Gets the ID of this block.
*
* @return The ID of this block. */
public int getId() {
return id;
}
/** Gets the Data for this block.
*
* @return The Data of this block. */
public byte getData() {
return data;
}
/** Sets the Data for this block.
*
* @param data The Data to set for this block. */
public void setData(byte data) {
this.data = data;
}
@Override
public Object clone() {
try {
SimpleBlock s = (SimpleBlock) super.clone();
return s;
}
catch (CloneNotSupportedException e) {
KenetiPrereq.journal.fine("CloneNotSupportedException: SimpleBlock " + this.toString());
throw new Error(e);
}
}
@Override
public String toString() {
return "{SimpleBlock:" + this.id + ":" + this.data + "}";
}
@Override
public int hashCode() {
return this.toString().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof SimpleBlock) return (this.id == ((SimpleBlock) obj).id) && (this.data == ((SimpleBlock) obj).data);
if (obj instanceof ItemStack) return (this.id == ((ItemStack) obj).getTypeId()) && (this.data == ((ItemStack) obj).getData().getData());
if (obj instanceof Block) return (this.id == ((Block) obj).getTypeId()) && (this.data == ((Block) obj).getData());
return false;
}
}
// The Map holding the value
private LinkedHashMap<SimpleBlock, LinkedList<Location>> locationsmap;
// I create the SimpleBlock object like this
SimpleBlock sb = new SimpleBlock(758, (byte) 14);
// I add the locations with the SimpleBlock object as the key.
locationsmap.put(sb, locations);
// so after getting the map in a local variable..
LinkedList<Location> locations = locationsMap.get(new SimpleBlock(758, (byte) 14));
When I try to get the object using the same creation data, it doesn't see the object in the map (although I see it when stepping the code, its in there for sure)
My question is, how doesn't this currently work?, I'm sure i've done the required steps to make the object equal?
Thank you in advance :D
Upvotes: 1
Views: 127
Reputation: 14746
The implementation of equals and hashcode does not satisfy the contract required (see http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29).
In a nutshell, the SimpleBlock object can equal to another object, but have a different hashcode
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.
fix that, and i think you'll fix your problem.
Edit: also, use a library to build the equals and hashcode methods will make it easier: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html and https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html
Upvotes: 1