81

Map キーとしてバイト配列を使用することに問題はありますか? new String(byte[])とハッシュすることもできますがString、 を使用する方が簡単byte[]です。

4

13 に答える 13

84

キーの参照の等価性のみが必要な場合は問題ありません。配列は、おそらく必要な方法で「値の等価性」を実装しません。例えば:

byte[] array1 = new byte[1];
byte[] array2 = new byte[1];

System.out.println(array1.equals(array2));
System.out.println(array1.hashCode());
System.out.println(array2.hashCode());

次のように出力します。

false
1671711
11394033

(実際の数値は関係ありません。数値が異なるという事実は重要です。)

あなたが実際に平等を望んでいると仮定すると、 を含み、byte[]平等とハッシュコード生成を適切に実装する独自のラッパーを作成することをお勧めします。

public final class ByteArrayWrapper
{
    private final byte[] data;

    public ByteArrayWrapper(byte[] data)
    {
        if (data == null)
        {
            throw new NullPointerException();
        }
        this.data = data;
    }

    @Override
    public boolean equals(Object other)
    {
        if (!(other instanceof ByteArrayWrapper))
        {
            return false;
        }
        return Arrays.equals(data, ((ByteArrayWrapper)other).data);
    }

    @Override
    public int hashCode()
    {
        return Arrays.hashCode(data);
    }
}

ByteArrayWrapper(etc)のキーとして ,を使用した後にバイト配列内の値を変更するとHashMap、キーを再度検索する際に問題が発生することに注意してください...必要にByteArrayWrapper応じて、コンストラクターでデータのコピーを取得できます、しかし、バイト配列の内容を変更しないことがわかっている場合、明らかにパフォーマンスが無駄になります。

ByteBufferEDIT:コメントで述べたように、これ(特にそのByteBuffer#wrap(byte[])メソッド)にも使用できます。必要のない余分な能力がすべてあることを考えると、それが本当に正しいことなのかどうかはわかりByteBufferませんが、それはオプションです.

于 2009-06-29T13:06:12.780 に答える
65

問題は、がとにbyte[]オブジェクト ID を使用するため、equalshashCode

byte[] b1 = {1, 2, 3}
byte[] b2 = {1, 2, 3}

では一致しませんHashMap。次の 3 つのオプションが表示されます。

  1. でラップしStringますが、エンコーディングの問題に注意する必要があります (バイト -> 文字列 -> バイトが同じバイトを与えることを確認する必要があります)。
  2. 使用しますList<Byte>(メモリの負荷が高くなる可能性があります)。
  3. 独自のラッピング クラスを作成し、バイト配列の内容を記述hashCodeして使用します。equals
于 2009-06-29T13:10:22.680 に答える
47

これには ByteBuffer を使用できます (これは基本的に、コンパレータを使用した byte[] ラッパーです)

HashMap<ByteBuffer, byte[]> kvs = new HashMap<ByteBuffer, byte[]>();
byte[] k1 = new byte[]{1,2 ,3};
byte[] k2 = new byte[]{1,2 ,3};
byte[] val = new byte[]{12,23,43,4};

kvs.put(ByteBuffer.wrap(k1), val);
System.out.println(kvs.containsKey(ByteBuffer.wrap(k2)));

印刷します

true
于 2012-12-30T00:32:15.420 に答える
11

を使用できますjava.math.BigIntegerBigInteger(byte[] val)コンストラクタがあります。これは参照型なので、ハッシュテーブルのキーとして使用できます。And.equals().hashCode()は、それぞれの整数として定義されています。つまり、BigInteger は byte[] 配列として一貫した equals セマンティクスを持っています。

于 2011-11-12T00:11:52.270 に答える
5

答えが最も単純な代替案を指摘していないことに非常に驚いています。

はい、HashMap を使用することはできませんが、代わりに SortedMap を使用することを誰も妨げません。唯一のことは、配列を比較する必要がある Comparator を書くことです。HashMap ほどパフォーマンスは高くありませんが、単純な代替手段が必要な場合は、次のようにします (実装を非表示にする場合は、SortedMap を Map に置き換えることができます)。

 private SortedMap<int[], String>  testMap = new TreeMap<>(new ArrayComparator());

 private class ArrayComparator implements Comparator<int[]> {
    @Override
    public int compare(int[] o1, int[] o2) {
      int result = 0;
      int maxLength = Math.max(o1.length, o2.length);
      for (int index = 0; index < maxLength; index++) {
        int o1Value = index < o1.length ? o1[index] : 0;
        int o2Value = index < o2.length ? o2[index] : 0;
        int cmp     = Integer.compare(o1Value, o2Value);
        if (cmp != 0) {
          result = cmp;
          break;
        }
      }
      return result;
    }
  }

この実装は他の配列に合わせて調整できます。注意しなければならない唯一のことは、等しい配列 (= 等しいメンバーで等しい長さ) は 0 を返さなければならず、決定的な順序があることです。

于 2016-07-24T13:44:08.250 に答える
1

ByteArrKey のようなクラスを作成し、hashcode と equal メソッドをオーバーロードする必要があります。それらの間の契約を覚えておいてください。

これにより、バイト配列の最後に追加された 0 エントリをスキップできるため、柔軟性が高まります。特に、他のバイト バッファから一部のみをコピーする場合に当てはまります。

このようにして、両方のオブジェクトがどのように等しいかを決定します。

于 2015-10-22T11:58:07.017 に答える
1

Java の配列は必ずしもhashCode()andequals(Object)メソッドを直感的に実装するとは限りません。つまり、2 つの同一のバイト配列が必ずしも同じハッシュ コードを共有するとは限らず、必ずしも等しいと主張するとは限りません。これら 2 つの特性がないと、HashMap は予期しない動作をします。

したがって、HashMap のキーとして使用しないことをお勧めします。byte[]

于 2009-06-29T13:05:44.000 に答える
0

Arrays.toString(バイト)

于 2009-11-17T03:15:07.983 に答える
0

デフォルトの配列実装の代わりに Arrays.equals と Array.hashCode を使用する必要があるため、問題が発生します

于 2009-06-29T13:06:48.410 に答える
0

Base32 または Base64 を使用して byte[] を「安全な」文字列に変換することもできます。次に例を示します。

byte[] keyValue = new byte[] {…};
String key = javax.xml.bind.DatatypeConverter.printBase64Binary(keyValue);

もちろん、上記には次のような多くのバリエーションがあります。

String key = org.apache.commons.codec.binary.Base64.encodeBase64(keyValue);
于 2014-03-07T12:35:21.783 に答える