所以我有一个小问题,我无法解决这个问题。
我需要将一个类对象作为一个键存储在一个映射中,然后由一个新创建的对象查找该映射。我有一个实现Cloneable
并覆盖toString
,hashCode
和equals
的类,但似乎该对象是唯一的,无论我如何创建要用作的对象从地图中检索值的键,应该与键匹配的新对象不会。
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));
当我尝试使用相同的创建数据获取对象时,它没有在地图中看到对象(虽然我在步进代码时看到它,但它肯定在那里)
我的问题是,这目前的工作原理是什么?我确定我已经完成了使对象相等的必要步骤?
提前谢谢你:D
答案 0 :(得分:1)
equals和hashcode的实现不满足所需的合同(参见http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29)。
简而言之,SimpleBlock对象可以等于另一个对象,但具有不同的哈希码
如果两个对象根据equals(Object)方法相等,那么 必须在两个对象中的每一个上调用hashCode方法 相同的整数结果。
解决这个问题,我认为你可以解决问题。
编辑:另外,使用库来构建equals和hashcode方法会更容易:https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html和https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html