0

しばらく調査を行って古い投稿を調べた後、文字列がキーである Java で Hashmap または Hashtable を使用すると、ハッシュの最初の「ラウンド」が各文字列オブジェクト hashCode に適用されることに気付きました (明らかに 2 番目のハッシュがあります)。 )の結果に適用される関数でint hashCode()、デフォルトint hashCode()ではメモリ内の呼び出し元の場所と何らかの関係があります(私が読んだものから)。そうは言っても、開発者が定義したキーのクラスを含むマップがある場合int hashCode()、オブジェクトのいくつかの異なるフィールドをオーバーライドして使用して、各オブジェクトに対して可能な限り一意の int を返すことができることを読みました。ただし、プリミティブ型の配列を含む以下のコード フラグメントを検討してください。

import java.util.HashMap;

public class test
{ 

    public static void main(String[] args) { 

        HashMap<char[], int[] > map = new HashMap<char[], int[]>();

        String s = "Hello, World";

        int x[] = { 1, 2, 3, 4, 5 };

        map.put( s.toCharArray(), x );

        x = map.get( s );

        for ( int i : x )
            System.out.print( i );
    } 
}

NullPointerExceptionもちろん、map.get( s );null を返すため、プログラムはクラッシュします。map.put()と の間に2 つの異なる参照があるため、これが発生したと思われますmap.get()。プログラムに出力してもらいたいのは、1 2 3 4 5 です。

私の質問: 上記のコード フラグメントを取得して、キーの値とキーの参照によってキーを検索するにはどうすればよいですか? つまり、プログラムに 1 2 3 4 5 を出力させるにはどうすればよいでしょうか。

編集:ハッシュマップをルックアップテーブルとして使用しています。ファイルから文字列を読み取っていますが、読み取ったばかりの文字列がテーブルにあるかどうかをすばやく判断する方法が必要です。

4

4 に答える 4

3

文字列をマップのキーとして使用するだけです。

HashMap<String, int[] > map = new HashMap<String, int[]>();
String key = "array1";
int x[] = { 1, 2, 3, 4, 5 };
map.put( key, x );

文字列は不変であるため、マップのキーとして適しています。

別の配列の追加:

String key2 = "array2";
int x2[] = { 6, 7, 8, 9, 10 };
map.put( key2, x2 );

出力値:

x = map.get( key );
for ( int i : x )
    System.out.print( i + " " );
}

与える

1 2 3 4 5

x = map.get( key2 );
for ( int i : x )
    System.out.print( i + " " );
}

与える

6 7 8 9 10

于 2014-07-18T10:42:29.917 に答える
2
  1. 「2ラウンドのハッシュがあることをどこかで読んでください」。いいえ。文字列がどのようにハッシュされるかを見たい場合は、コードを見てください。
  2. ハッシュ マップの基本的な契約は、キーが同じハッシュを持ち、それらのequals関数が等しい場合にアイテムを取得することです。自分自身を文字列と適切に比較できるようにするchar[]オーバーライドがあるのはなぜだと思いますか? equalsそれともお互いの間でも?equals をオーバーライドせ、同じインスタンスの場合にのみ true を返します。
  3. キーに配列を使用しています。それは可能ですが、ほとんどの上級開発者はあなたに怒鳴るでしょう。それらを比較する良い方法はありません: Object.equals (デフォルトで使用される) は、配列を再現できないことを意味します -まったく同じ objectを使用する必要があります。Arrays.equals (または内容を比較するための同様の手段) を使用すると、キーとして変更可能なオブジェクトがあることを意味します - BAD

あなたのコメントによると、文字列を編集できるようにしたいことを理解しています。地図に載せる前で結構です。ただし、オブジェクトがマップ内のキーである場合は、ハッシュ コードまたは equals を変更する可能性がある方法でオブジェクトを変更しないでください。これを行う最善の方法は、カスタム オブジェクトを使用することです。配列はこれには適していません。

値がマップ内にあるときにその場で値を本当に変更したい場合は、 a を使用します(BiMapまたは、自分で行うことを行いforcePutます)。

于 2014-07-18T10:54:11.440 に答える
1

これを行うには多くの方法があります。実行できる最小の変更の 1 つは、 をchar[]呼び出す前に単純に保存put()し、同じものを の引数として使用することget()です。

char[] charArray = s.toCharArray();
map.put(charArray, x);
x = map.get(charArray);

ここで重要なことは、以前と同じオブジェクトを に使用する必要があるということget()です put()

于 2014-07-18T10:42:23.173 に答える
0

オラクルのドキュメントから

public V get(Object key)

Returns the value to which the specified key is mapped, or null if this 
map contains no mapping for the key.
More formally, if this map contains a mapping from a key k to a value v 
such that (key==null ? k==null : key.equals(k)), then this method returns v; 
otherwise it returns null.

そして明らかに s.equals(s.toCharArray()) は false です。それらは同じクラスではありません。

ただし、場合に true を返す方法で equals() をオーバーライドするクラスをキーとして使用できます。例えば:

class MyCharArray {

   private char[] data;

   @Override
   public boolean equals(Object o) {
       if (o instanceOf String) {
           return data.equals(o.toCharArray);
       else {
           return false;
       }
   }

   ...
}
于 2014-07-18T10:49:15.983 に答える