質問
だけに見られる問題を用いたバイト配列として地図ーション-キーとは何ですか。えもん new String(byte[])
およびハッシュによる String
それでいて簡単に利用 byte[]
.
解決
問題は byte[]
使用オブジェクトのアイデンティティ equals
や hashCode
, う
byte[] b1 = {1, 2, 3}
byte[] b2 = {1, 2, 3}
一致しなくなり、 HashMap
.いつのオプション:
- 包装に
String
, 、その場合に気を付ける必要がありエンコード問題にするのに必要である、バイト->String-->byteときと同じバイト単位)。 - 使用
List<Byte>
(高価になることができけいたしました。 - 自分の包装クラスは、書面に
hashCode
やequals
コンテンツの使用のバイト配列になります。
他のヒント
それはあまりにも長い間あなただけのキーの参照の等価をしたいと大丈夫だ - 配列は、おそらくしたいと思う方法で、「価値の平等」を実装していません。たとえばます:
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
におけるキー(など)として、HashMap
を使用した後、バイト配列内の値を変更する場合は、もう一度キーを探して問題があるでしょう...あなたがデータのコピーを取ることができることに注意してくださいあなたがしたい場合ByteArrayWrapper
コンストラクタ、しかし、あなたはを知っていれば、明らかにそれはのバイト配列の内容を変更されることはありません、パフォーマンスの無駄になります。
編集:コメントで述べたように、あなたも(このためByteBuffer
を使用することができ、特に、その<のhref = "http://docs.oracle.com/javase/7/docs/api/java/nio/ #ラップ%28byte%5B%5D%29" REL = "noreferrer"> ByteBuffer#wrap(byte[])
の方法)ByteBuffer.html。私はあなたが必要としませんが、それはオプションだByteBuffer
sが持っているすべての余分な能力を考えると、それは本当に正しいことだかどうかわからない。
我々は(これは、基本的には、比較器のバイト[]ラッパーである)、このためのByteBufferを使用することができる
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
あなたはjava.math.BigInteger
を使用することができます。それはBigInteger(byte[] val)
コンストラクタを持っています。これは、参照型なので、ハッシュテーブルのキーとして使用することができます。そして.equals()
と.hashCode()
はBigIntegerのバイト[]配列としてセマンティクスを一貫等しいた意味し、それぞれの整数で定義したとおりである。
私は答えが最も簡単な選択肢を指摘されていないことを非常に驚いています。
はい、HashMapを使用することはできませんが、誰も代替としてのSortedMapを使用してもかまいません。唯一のことは、配列を比較する必要がコンパレータを書くことです。これは、HashMapのほどパフォーマンスはありませんが、簡単な選択肢をしたい場合は、ここであなたは(あなたが実装を隠したい場合は、地図でのSortedMapを置き換えることができます)行きます:
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を返すとしなければならないことであるあなたがdetermistic順序を持っていること
私は、Javaの配列は必ずしも直感的hashCode()
とequals(Object)
メソッドを実装していないと信じています。つまり、二つの同一のバイト配列は、必ずしも同一のハッシュコードを共有しないであろうと、それらは必ずしも同じであると主張しないであろう。これらの二つの特徴がなければ、あなたのHashMapが予期しない動作をします。
そこで、私は、HashMapのキーとしてbyte[]
を使用しての の反対をお勧めします。
あなたはそれらの間の契約を覚え、ByteArrKeyようなクラスの気にいらないと過負荷ハッシュコードと同じメソッドを作成して使用する必要があります。
これはあなたがあなたが他のバイトのバッファ形式のみ一部をコピー、特別場合は、バイト配列の最後に追加されている0エントリーをスキップすることができるよう、より大きな柔軟性が得られます。
あなたは、両方のオブジェクトが等しいどうあるべきかを決定します。この道ます。
私はあなたがデフォルトの配列の実装の代わりにをArrays.equalsとArray.hashCodeを、使用する必要がありますので、問題を参照してください。
Arrays.toString(バイト)
あなたはまた、例えば、Base32またはBase64のを使用して「安全」の文字列に[]バイトを変換することができ
byte[] keyValue = new byte[] {…};
String key = javax.xml.bind.DatatypeConverter.printBase64Binary(keyValue);
もちろん、上記の多くの亜種があり、同様ます:
String key = org.apache.commons.codec.binary.Base64.encodeBase64(keyValue);
ここでのTreeMap、コンパレータインタフェースおよびJavaメソッドjava.util.Arrays.equals(バイト[]、バイト[])を使用して溶液である。
注:マップ内の順序は、この方法では関係ありません。
SortedMap<byte[], String> testMap = new TreeMap<>(new ArrayComparator());
static class ArrayComparator implements Comparator<byte[]> {
@Override
public int compare(byte[] byteArray1, byte[] byteArray2) {
int result = 0;
boolean areEquals = Arrays.equals(byteArray1, byteArray2);
if (!areEquals) {
result = -1;
}
return result;
}
}