【问题标题】:how to compare the Java Byte[] array?如何比较 Java Byte[] 数组?
【发布时间】:2012-03-18 23:09:24
【问题描述】:
public class ByteArr {

    public static void main(String[] args){
        Byte[] a = {(byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00};
        Byte[] b = {(byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00};
        byte[] aa = {(byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00};
        byte[] bb = {(byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00};

        System.out.println(a);
        System.out.println(b);
        System.out.println(a == b);
        System.out.println(a.equals(b));

        System.out.println(aa);
        System.out.println(bb);
        System.out.println(aa == bb);
        System.out.println(aa.equals(bb));
    }
}

我不知道为什么它们都打印错误。

当我运行“java ByteArray”时,答案是“false false false false”。

我认为a[]等于b[]但是JVM告诉我我错了,为什么?

【问题讨论】:

标签: java


【解决方案1】:

Arrays.equals 不足以作为比较器,您无法检查地图是否包含数据。我从Arrays.equals复制代码,修改为构建Comparator

class ByteArrays{
    public static <T> SortedMap<byte[], T> newByteArrayMap() {
        return new TreeMap<>(new ByteArrayComparator());
    }

    public static SortedSet<byte[]> newByteArraySet() {
        return new TreeSet<>(new ByteArrayComparator());
    }

    static class ByteArrayComparator implements Comparator<byte[]> {
        @Override
        public int compare(byte[] a, byte[] b) {
            if (a == b) {
                return 0;
            }
            if (a == null || b == null) {
                throw new NullPointerException();
            }

            int length = a.length;
            int cmp;
            if ((cmp = Integer.compare(length, b.length)) != 0) {
                return cmp;
            }

            for (int i = 0; i < length; i++) {
                if ((cmp = Byte.compare(a[i], b[i])) != 0) {
                    return cmp;
                }
            }

            return 0;
        }
    }
}

【讨论】:

    【解决方案2】:

    你也可以使用 org.apache.commons.lang.ArrayUtils.isEquals()

    【讨论】:

      【解决方案3】:

      因为数组的==equals()方法都没有比较内容;两者都只评估对象身份(== 总是这样做,并且equals() 不会被覆盖,因此正在使用来自Object 的版本)。

      要比较内容,请使用Arrays.equals()

      【讨论】:

        【解决方案4】:

        Java 字节比较,

        public static boolean equals(byte[] a, byte[] a2) {
                if (a == a2)
                    return true;
                if (a == null || a2 == null)
                    return false;
        
                int length = a.length;
                if (a2.length != length)
                    return false;
        
                for (int i = 0; i < length; i++)
                    if (a[i] != a2[i])
                        return false;
        
                return true;
            }
        

        【讨论】:

          【解决方案5】:

          我寻找了一个数组包装器,它可以与 guava TreeRangeMap 一起使用。该类不接受比较器。

          经过一番研究,我意识到 JDK 的 ByteBuffer 具有此功能,它不会复制原始数组,这很好。 此外,您可以更快地与 ByteBuffer::asLongBuffer 一次 8 个字节进行比较(也不会复制)。默认情况下 ByteBuffer::wrap(byte[]) 使用 BigEndian,因此顺序关系与比较单个字节相同。

          【讨论】:

            【解决方案6】:

            为什么 a[] 不等于 b[]? 因为在Byte[]byte[] 上真正调用的equals 函数是Object.equals(Object obj)。该函数只比较对象标识,不比较数组的内容。

            【讨论】:

              【解决方案7】:

              有一种更快的方法:

              Arrays.hashCode(arr1) == Arrays.hashCode(arr2)
              

              【讨论】:

              • “更快”是指“更慢”。
              【解决方案8】:

              试试这个:

              boolean blnResult = Arrays.equals(byteArray1, byteArray2);
              

              我也不确定,但试试这个可能有效。

              【讨论】:

                【解决方案9】:

                您还可以使用Apache Directory 中的ByteArrayComparator。除了 equals 之外,它还可以让您比较一个数组是否比另一个数组大于

                【讨论】:

                  【解决方案10】:

                  如果您尝试将数组用作通用 HashMap 键,那是行不通的。考虑创建一个包含数组的自定义包装对象,其equals(...)hashcode(...) 方法从java.util.Arrays 方法返回结果。比如……

                  import java.util.Arrays;
                  
                  public class MyByteArray {
                     private byte[] data;
                  
                     // ... constructors, getters methods, setter methods, etc...
                  
                  
                     @Override
                     public int hashCode() {
                        return Arrays.hashCode(data);
                     }
                  
                     @Override
                     public boolean equals(Object obj) {
                        if (this == obj)
                           return true;
                        if (obj == null)
                           return false;
                        if (getClass() != obj.getClass())
                           return false;
                        MyByteArray other = (MyByteArray) obj;
                        if (!Arrays.equals(data, other.data))
                           return false;
                        return true;
                     }
                  
                  
                  }
                  

                  这个包装类的对象可以作为HashMap&lt;MyByteArray, OtherType&gt; 的键正常工作,并且允许干净地使用equals(...)hashCode(...) 方法。

                  【讨论】:

                    【解决方案11】:

                    你看过Arrays.equals()吗?

                    编辑:如果根据您的评论,问题是使用字节数组作为 HashMap 键,请参阅this question

                    【讨论】:

                    • 如果我有一个 'HashMap' 和我 'put(a, buffer)',,,, if i 'print(map.containsKey(b))' 它打印“假”,是不是同一个道理???
                    【解决方案12】:

                    由于 byte[] 是可变的,如果它是同一个对象,它只会被视为 .equals()

                    如果你想比较内容你必须使用Arrays.equals(a, b)

                    顺便说一句:这不是我设计的方式。 ;)

                    【讨论】:

                      【解决方案13】:

                      它们返回 false 是因为您正在测试对象身份而不是值相等。这将返回 false,因为您的数组实际上是内存中的不同对象。

                      如果您想测试值是否相等,请使用java.util.Arrays 中的方便比较函数

                      例如

                      import java.util.Arrays;
                      
                      '''''
                      
                      Arrays.equals(a,b);
                      

                      【讨论】:

                        【解决方案14】:

                        因为它们不相等,即:它们是内部具有相同元素的不同数组。

                        尝试使用Arrays.equals()Arrays.deepEquals()

                        【讨论】:

                        • 这是 Java 废话的一部分:为什么要使用来自不同类的静态方法来比较另一个类中的对象?那就是:他们为什么不重写equals() 方法?
                        【解决方案15】:

                        如果您想比较包含原始类型值(如字节)的数组的实际内容,请使用Arrays.equals()

                        System.out.println(Arrays.equals(aa, bb));
                        

                        使用Arrays.deepEquals 比较包含对象的数组。

                        【讨论】:

                        • 如果我有一个 'HashMap' 和我 'put(a, buffer)',,,, if i 'print(map.containsKey(b))' 它打印“假”,是不是同一个道理???
                        • @Lazy:是的,原因是一样的……你不能在地图中使用原始字节[]作为键……阅读更多:stackoverflow.com/questions/1058149/…
                        猜你喜欢
                        • 2015-03-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多