簡體   English   中英

HashMap的ContainsKey不適用於Custom Class作為鍵

[英]ContainsKey of HashMap does not work with a Custom Class as key

我有一個要在HashMap中使用的自定義類MarioState。 該類表示馬里奧游戲的狀態空間中的可能狀態。 下面是類MarioState的簡化版本。

在我的HashMap中,我想存儲這些狀態。 但是,比較兩個MarioState的財產時,不應考慮MarioState的財產。 例如,如果一個MarioState的“ sticked”屬性設置為true且距離為30,而另一個MarioState的“ sticked”屬性設置為true,但距離值不同(例如20),則仍應將它們視為相同。

我知道要使其在我的HashMap中起作用,我必須實現.equals()和.hashcode()方法,這就是我所做的(通過讓它們由InteliJ IDE自動生成)。

public class MarioState{

    // Tracking the distance Mario has moved.
    private int distance;
    private int lastDistance;

    // To keep track of if Mario is stuck or not.
    private int stuckCount;
    private boolean stuck;

    public MarioState(){
        stuckCount = 0;
        stuck = false;

        distance = 0;
        lastDistance = 0;
    }

    public void update(Environment environment){

        // Computing the distance
        int tempDistance = environment.getEvaluationInfo().distancePassedPhys;
        distance = tempDistance - lastDistance;
        lastDistance = tempDistance;

        // If Mario hasn't moved for over 25 turns then this means he is stuck.
        if(distance == 0){
            stuckCount++;
        } else {
            stuckCount = 0;
            stuck = false;
        }

        if(stuckCount > 25){ stuck = true; }
    }

    public float calculateReward(){
        float reward = 0f;
        reward += distance * 2;
        if(stuck){ reward += -20; }
        return reward;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        MarioState that = (MarioState) o;

        if (stuck != that.stuck) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return (stuck ? 1 : 0);
    }  
}

然而,問題在於,在運行代碼時,某些鍵不應該根據其.equals()和.hashcode()函數而被認為是不同的。 是什么原因造成的? 我忘記了什么嗎?

在HashMap中插入狀態時使用的代碼(如有必要,可以提供其他信息):

public float[] getActionsQValues(MarioState state){
    if(!table.containsKey(state)) {
        float[] initialQvalues = getInitialQvalues(state);
        table.put(state, initialQvalues);
        return initialQvalues;
    }
    return table.get(state);
}

在調試模式下的屏幕快照顯示了我的表,其中包含兩個具有不同值的鍵,但是鍵本身是相同的(但是在HashMap中,它被認為是不同的)。

調試模式的屏幕截圖

您的哈希碼計算和相等性比較都基於stuck -但這會隨着時間而變化。

如果您在將對象添加為哈希映射中的鍵之后對對象進行了更改(以使哈希代碼發生更改的方式),則在以后您請求它時將找不到該鍵-因為在該鍵被存儲時存儲的哈希碼首次添加的將不再與其當前的哈希碼相同。

盡可能避免在地圖中使用可變對象作為鍵(即使不使用哈希碼的TreeMap如果以更改相對順序的方式更改對象,也會遇到相同的問題)。 如果必須將可變對象用作地圖中的鍵,則應避免在將它們添加為鍵后對其進行突變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM