1

When I write

String str1 = new String("hello");
String str2 = new String("hello");

afaik, even though the String contents are same, str1 and str2 will point to separate memory location as it will refer in heap and not in pool.

In this case, when I execute the below program, why is it giving me the value when the two instances (Key) of string are different? then why the same is not happening with user defined objects?

String str1 = new String("hello");
String str2 = new String("hello");
AB obj1 = new AB();
BC obj2 = new BC();

HashMap h = new HashMap();
h.put(str1, "data");
h.put(obj1, "data1");

System.out.println(h.get(str2));
System.out.println(h.get(obj2));

class AB {
  int code = 10;
}

class BC {
  int code = 10;
}

Output:

data
null
4

6 に答える 6

1

HashMap.get() 関数は Object.hashCode() メソッドを呼び出してキー値を作成します。ただし、String クラスはこのメソッドをオーバーライドし、値から計算します。これら (AB および BC) クラスの hashCode 関数をオーバーライドすると、同じ解決策が見つかります。

文字列 hashCode():

public int hashCode() {
int h = hash;
    int len = count;
if (h == 0 && len > 0) {
    int off = offset;
    char val[] = value; // get value of string.

        for (int i = 0; i < len; i++) {
            h = 31*h + val[off++];
        }
        hash = h;
    }
    return h;
}

そして、これが HashMap.get() メソッドです

public V get(Object key) {
    if (key == null)
        return getForNullKey();
    int hash = hash(key.hashCode());// it calculate at here.
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
            return e.value;
    }
    return null;
}
于 2012-10-22T10:48:24.880 に答える
1

HashMap はequalsキーの比較に使用されるためです。2 つの文字列は異なるインスタンスですが、同じです。

カスタム オブジェクトは同じ型ではないため、同じにすることはできません。equals同じ型だったとしても、から継承しObjectたメソッドをオーバーライドしない限り、( で作成された) 2 つの異なるインスタンスnewは等しくなりません。

をオーバーライドする場合は、予期しない動作を避けるためequalsにもオーバーライドする必要があることに注意してください。hashCode

于 2012-10-22T10:38:57.590 に答える
0

マップは、クラスの hashCode および equals メソッドを利用するような方法で実装されます。

まず、クラスのインスタンスをマップに追加すると、マップの実装によってそのインスタンスがバケットに配置されます。これが、マップ内のバケットが効果的に分散されるようにするために、hashCode を正しく実装することが重要である理由です。

equals メソッドの使用は、バケット内のどのインスタンスが目的のインスタンスであるかを判断することです。したがって、equals を正しく実装することが重要です。

あなたの場合、 String は hashCode と equals を正しく実装していますが、ユーザー定義のオブジェクトは同じタイプではないため、等しくすることはできません (とにかく equals または hashCode をオーバーライドしません)。

于 2012-10-22T10:47:23.420 に答える
0

ハッシュマップのキーとしていくつかのオブジェクトを使用しているときに合意があります。 String クラスがそれを行うので、
hashcode と equals メソッドをオーバーライドする必要があります 。希望する方法で AB と BC の hashcode と equals メソッドをオーバーライドすると
、最初の sysout から「データ」を取得します。
2 番目の sysout から data1 を取得します

str1 と str2 は別々のメモリ位置を指しません

于 2012-10-22T10:40:16.827 に答える
0

HashMap は最初に文字列オブジェクトのハッシュコードに基づいて正しいバケットを見つけるため、バケットが見つかったら、Equals メソッドを呼び出してキーを比較します。

Equals 比較は String クラスによってオーバーライドされるため、参照だけでなく内容にも基づいて比較されることに注意してください。

于 2012-10-22T10:40:59.010 に答える
0

String内容が比較されます。実際のオブジェクトまたは参照ではありません。

str1str2の内容は同じなので、 からの値が得られHashMapます。

HashMap はequalsメソッドを使用して、その中の正確なキーを検索します。str1.equals(str2)結果がであるためtrue、キーが見つかり、getメソッドは値を返します。

クラスを次のように編集してみてください。

class AB 
{   
    int code = 10; 
    public boolean equals(Object argument)
    {
        if(argument instanceof AB || argument instanceof BC)
            return true;
        return false;
    }
}  

class BC 
{   
    int code = 10; 
    public boolean equals(Object argument)
    {
        if(argument instanceof AB || argument instanceof BC)
            return true;
        return false;
    }
}

これで、2 番目System.out.println(h.get(obj2));のステートメントもマップされたデータを返します。

于 2012-10-22T10:41:06.200 に答える