我从Text构造函数中获得了一些没有任何意义的行为。基本上,如果我从String构造一个Text对象,它不等于我从字节构造的另一个Text对象,即使getBytes()为两个对象返回相同的值。
所以我们得到这样奇怪的东西:
//This succeeds
assertEquals(new Text("ACTACGACCA_0"), new Text("ACTACGACCA_0"));
//This succeeds
assertEquals((new Text("ACTACGACCA_0")).getBytes(), (new Text("ACTACGACCA_0")).getBytes());
//This fails. Why?
assertEquals(new Text((new Text("ACTACGACCA_0")).getBytes()), new Text("ACTACGACCA_0"));
当我尝试访问hashmap时会出现这种情况。在这里,我正在尝试根据org.apache.hadoop.hbase.KeyValue.getRow()返回的值进行查找:
//This succeeds
assertEquals((new Text("ACTACGACCA_0")).getBytes(), keyValue.getRow());
//This returns a value
hashMap.get(new Text("ACTACGACCA_0"));
//This returns null. Why?
hashMap.get(new Text(keyValue.getRow()));
那么这里发生了什么,我该如何应对呢?这与编码有关吗?
感谢克里斯指出我正确的方向。所以,一点背景:从调用htable.put()中捕获keyValue对象(使用Mockito ArgumentCaptor)。基本上,我有这段代码:
byte[] keyBytes = matchRow.getKey().getBytes();
RowLock rowLock = hTable.lockRow(keyBytes);
Get get = new Get(keyBytes, rowLock);
SetWritable<Text> toWrite = new SetWritable<Text>(Text.class);
toWrite.getValues().addAll(matchRow.getMatches(hTable, get));
Put put = new Put(keyBytes, rowLock);
put.add(Bytes.toBytes(MatchesByHaplotype.MATCHING_COLUMN_FAMILY), Bytes.toBytes(MatchesByHaplotype.UID_QUALIFIER),
SERIALIZATION_HELPER.serialize(toWrite));
hTable.put(put);
其中matchRow.getKey()返回一个文本对象。你在这看到问题了吗?我正在添加所有字节,包括无效字节。所以我创建了一个很好的辅助函数来执行此操作:
public byte[] getValidBytes(Text text) {
return Arrays.copyOf(text.getBytes(), text.getLength());
}
并将该块的第一行更改为:
byte[] keyBytes = SERIALIZATION_HELPER.getValidBytes(matchRow.getKey());
问题解决了!回想起来:哇,多么讨厌的虫子!我认为它归结为Text.getBytes()的行为非常不友好。它不仅会返回您可能没有预期的内容(无效字节),Text对象也没有返回有效字节的函数!你会认为这是一个常见的用例。也许他们将来会添加这个?
答案 0 :(得分:3)
出于同样的原因,以下情况失败:
Assert.assertEquals((new Text("ACTACGACCA_0")).getLength(), (new Text("ACTACGACCA_0")).getBytes().length);
getBytes()
返回后备字节数组,但根据API,字节仅有效Text.getLength();
是的,这与编码有关 - CharsetEncoder.encode方法使用ByteBuffer,其大小最初分配为12 * 1.1字节(13)的长度,但实际有效字节数仍然只有12(如你只使用ASCII字符。)