Java字节数组集
我有一个Java字节数组集,java,set,Java,Set,我有一个byte[]s的散列集,我想测试一个新的byte[]是否在该集中。问题在于Java似乎在测试byte[]实例是否相同,而不是测试字节数组中的实际值是否相同 换句话说,考虑下面的代码: public class Test { public static void main(String[] args) { java.util.HashSet<byte[]> set=new java.util.HashSet<byte[]>();
byte[]
s的散列集,我想测试一个新的byte[]
是否在该集中。问题在于Java似乎在测试byte[]
实例是否相同,而不是测试字节数组中的实际值是否相同
换句话说,考虑下面的代码:
public class Test
{
public static void main(String[] args)
{
java.util.HashSet<byte[]> set=new java.util.HashSet<byte[]>();
set.add(new String("abc").getBytes());
System.out.println(set.contains(new String("abc").getBytes()));
}
}
公共类测试
{
公共静态void main(字符串[]args)
{
java.util.HashSet=new java.util.HashSet();
添加(新字符串(“abc”).getBytes());
System.out.println(set.contains(新字符串(“abc”).getBytes());
}
}
此代码打印出
false
,我希望它打印出true
。我应该怎么做呢?您可以定义自己的包装器类,但最简单的方法可能是将数组“包装”到ArrayList中,并使用哈希集您可以创建一个ByteArray
类,以您想要的方式包装字节数组并测试是否相等。然后您就有了一个集合
您可以使用ByteBuffer.wrap来包装每个字节数组,这将为您提供正确的equals和hashCode行为。只需小心调用ByteBuffer
(不要修改数组或推进其指针)的方法。您可以避免包装器和愚蠢的哈希代码问题(嘿,像byte[]这样的标准对象没有正确的哈希代码?)
使用TreeSet而不是HashSet,并在实例化时提供byte[]比较器:
Set<byte[]> byteATreeSet = new TreeSet<byte[]>(new Comparator<byte[]>() {
public int compare(byte[] left, byte[] right) {
for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) {
int a = (left[i] & 0xff);
int b = (right[j] & 0xff);
if (a != b) {
return a - b;
}
}
return left.length - right.length;
}});
Set byteATreeSet=新树集(新比较器(){
公共整数比较(字节[]左,字节[]右){
对于(int i=0,j=0;i
如果您从其他地方获得字节[]哈希集b,请在之前将变量a初始化为TreeSet,然后使用a.addAll(b);这样,即使b包含重复项,a也不会。Modern(从现在的解决方案开始)
import com.google.common.collect.ImmutableSet;
导入java.nio.ByteBuffer;
导入java.util.Set;
导入静态com.google.common.base.Charsets.UTF_8;
导入静态java.nio.ByteBuffer.wrap;
公共课刮刮
{
公共静态void main(字符串[]args)
{
最终设置bbs=ImmutableSet.of(wrap(“abc”.getBytes(UTF_8)).asReadOnlyBuffer());
System.out.println(“bbs.contains(ByteBuffer.wrap(\“abc\”.getBytes(Charsets.UTF_8)))=”+bbs.contains(wrap(“abc.getBytes(UTF_8)).asReadOnlyBuffer());
}
}
笔记:
在不提供字符集的情况下,决不能将字符串
转换为字节[]
。结果取决于默认的字符集
,默认的字符集通常不是好的,可以更改
.asReadOnlyBuffer()
很重要
创建一个新的只读字节缓冲区,该缓冲区共享此缓冲区的
内容。新缓冲区的内容将是此缓冲区的内容。
对该缓冲区内容的更改将在新缓冲区中可见;
但是,新缓冲区本身将是只读的,不允许
要修改的共享内容
两个缓冲器的位置、极限和标记值将是独立的
新缓冲区的容量、限制、位置和标记值将与此缓冲区的相同。
如果此缓冲区本身是只读的,则此方法的行为完全相同
与复制方法相同
在所有这些答案中,要小心更改集合中字节数组的任何元素;这样做将影响其哈希及其相等性,但不会更改其当前存储的哈希桶。值得注意的是,TreeSet的添加、删除、包含方法的时间复杂度比HashSet(O(lg n)vs O(1))差,这可能是一个重要因素。
import com.google.common.collect.ImmutableSet;
import java.nio.ByteBuffer;
import java.util.Set;
import static com.google.common.base.Charsets.UTF_8;
import static java.nio.ByteBuffer.wrap;
public class Scratch
{
public static void main(String[] args)
{
final Set<ByteBuffer> bbs = ImmutableSet.of(wrap("abc".getBytes(UTF_8)).asReadOnlyBuffer());
System.out.println("bbs.contains(ByteBuffer.wrap(\"abc\".getBytes(Charsets.UTF_8))) = " + bbs.contains(wrap("abc".getBytes(UTF_8)).asReadOnlyBuffer()));
}
}