Java 字节数组集

发布于 2024-09-07 22:34:25 字数 517 浏览 3 评论 0原文

我有一个 byte[] 的哈希集,我想测试该集合中是否有新的 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()));
    }
}

此代码打印出 false,我希望它打印出 true。我该怎么做呢?

I have a HashSet of byte[]s and I would like to test whether a new byte[] is in that set. The problem is that Java seems to be testing whether the byte[] instances are the same rather than testing whether the actual values in the byte arrays are the same.

In other words, consider the following code:

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()));
    }
}

This code prints out false and I would like it to print out true. How should I go about doing this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

抠脚大汉 2024-09-14 22:34:25

您可以使用 ByteBuffer.wrap 包装每个字节数组,这将为您提供正确的 equals 和 hashCode 行为。请注意在 ByteBuffer 上调用的方法(不要修改数组或提前其指针)。

You can wrap each byte array using ByteBuffer.wrap, which will provide the right equals and hashCode behavior for you. Just be careful what methods you call on the ByteBuffer (that you don't modify the array or advance its pointer).

活泼老夫 2024-09-14 22:34:25

您可以创建一个 ByteArray 类来包装字节数组并按照您想要的方式测试相等性。然后你就会有一个Set

You could create a ByteArray class that wraps the byte arrays and tests for equality the way you want. Then you'd have a Set<ByteArray>.

大姐,你呐 2024-09-14 22:34:25

您可以定义自己的包装类,但最简单的方法可能是将数组“包装”到 ArrayList 中并使用 HashSet

You could define your own wrapper class, but probably the easiest thing to do is to "wrap" the arrays into ArrayLists and use a HashSet<ArrayList>.

第七度阳光i 2024-09-14 22:34:25

现代(截至目前的解决方案)

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()));
    }
}

注意:

您不应该在不提供 Charset< 的情况下将 String 转换为 byte[] /code> 结果变得依赖于默认的 Charset 运行时,这通常不是一个好的字符集并且可以更改。

.asReadOnlyBuffer() 很重要!

创建一个新的只读字节缓冲区,共享此缓冲区的
内容。新缓冲区的内容将是该缓冲区的内容。
对此缓冲区内容的更改将在新缓冲区中可见;
然而,新缓冲区本身将是只读的,并且不允许
需要修改的共享内容。

两个缓冲区的位置、限制和标记值将是独立的。

新缓冲区的容量、限制、位置和标记值将与该缓冲区的容量、限制、位置和标记值相同。
如果此缓冲区本身是只读的,则此方法的行为完全相同
与复制方法相同。

Modern ( as of right now solution )

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()));
    }
}

NOTES:

You should never convert a String to a byte[] without providing a Charset the results become runtime dependant based on the default Charset which is usually not a good one and can change.

.asReadOnlyBuffer() is important!

Creates a new, read-only byte buffer that shares this buffer's
content. The content of the new buffer will be that of this buffer.
Changes to this buffer's content will be visible in the new buffer;
the new buffer itself, however, will be read-only and will not allow
the shared content to be modified.

The two buffers' position, limit, and mark values will be independent.

The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer.
If this buffer is itself read-only then this method behaves in exactly
the same way as the duplicate method.

苏佲洛 2024-09-14 22:34:25

您可以避免包装器和愚蠢的 hashCode 问题(嘿,像 byte[] 这样的标准东西没有 hashCode 对吧?):

使用 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;
   }});

如果您得到一个字节[] HashSet b 来自其他地方,将变量 a 初始化为 TreeSet,然后使用 a.addAll(b);这样,即使 b 包含重复项,a 也不会。

You can avoid wrappers and the stupid hashCode problem (hey, a standard thing like a byte[] doesn't have hashCode right?):

Use TreeSet instead of HashSet and provide a byte[] comparator at instantiation time:

  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;
   }});

If you get a byte[] HashSet b from somewhere else, initialize your variable a before as TreeSet and then use a.addAll(b); This way, even if b contained duplicates, a does not.

佞臣 2024-09-14 22:34:25

实施亚当·克鲁姆的想法。

public class ByteArraySet
{
    Set<BaWrapper> bws;

    public ByteArraySet()
    {
        bws = new HashSet<BaWrapper>();
    }

    public boolean contains(final byte[] a)
    {
        return bws.contains(new BaWrapper(a));
    }

    public boolean add(final byte[] a)
    {
        return bws.add(new BaWrapper(a));
    }

    public boolean remove(final byte[] a)
    {
        return bws.remove(new BaWrapper(a));
    }

    public  int size()
    {
        return bws.size();
    }

    private static class BaWrapper
    {
        byte[] a;

        BaWrapper(final byte[] a)
        {
            this.a = a;
        }

        @Override
        public boolean equals(final Object rhs)
        {
            return Arrays.equals(a, ((BaWrapper) rhs).a);
        }

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

Implementing Adam Crume's idea.

public class ByteArraySet
{
    Set<BaWrapper> bws;

    public ByteArraySet()
    {
        bws = new HashSet<BaWrapper>();
    }

    public boolean contains(final byte[] a)
    {
        return bws.contains(new BaWrapper(a));
    }

    public boolean add(final byte[] a)
    {
        return bws.add(new BaWrapper(a));
    }

    public boolean remove(final byte[] a)
    {
        return bws.remove(new BaWrapper(a));
    }

    public  int size()
    {
        return bws.size();
    }

    private static class BaWrapper
    {
        byte[] a;

        BaWrapper(final byte[] a)
        {
            this.a = a;
        }

        @Override
        public boolean equals(final Object rhs)
        {
            return Arrays.equals(a, ((BaWrapper) rhs).a);
        }

        @Override
        public int hashCode()
        {
            return Arrays.hashCode(a);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文