简体   繁体   English

使用HashMaps中的对象作为键

[英]Using objects in HashMaps as a Key

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. 我有一个实现Cloneable的类,并重写toStringhashCodeequals ,但是该对象似乎是唯一的,无论我如何创建用作键以从映射中检索值的对象,应匹配的新对象钥匙,不是。

The Object Class: 对象类:

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;
    }

}

Running Code 运行代码

// 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);

Later, in another class: 后来,在另一堂课中:

// 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 预先谢谢你:D

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 ). equals和hashcode的实现不满足所需的约定(请参阅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 简而言之,SimpleBlock对象可以等于另一个对象,但是具有不同的哈希码

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. 如果根据equals(Object)方法,两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。

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 编辑:此外,使用库来构建equals和hashcode方法将使其更容易: https : //commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.htmlhttps://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/HashCodeBuilder.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM