[java] how to compare the Java Byte[] array?

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

I do not know why all of them print false.

When I run "java ByteArray", the answer is "false false false false".

I think the a[] equals b[] but the JVM is telling me I am wrong, why??

This question is related to java

The answer is


As byte[] is mutable it is treated as only being .equals() if its the same object.

If you want to compare the contents you have to use Arrays.equals(a, b)

BTW: Its not the way I would design it. ;)


If you're trying to use the array as a generic HashMap key, that's not going to work. Consider creating a custom wrapper object that holds the array, and whose equals(...) and hashcode(...) method returns the results from the java.util.Arrays methods. For example...

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


}

Objects of this wrapper class will work fine as a key for your HashMap<MyByteArray, OtherType> and will allow for clean use of equals(...) and hashCode(...) methods.


have you looked at Arrays.equals()?

Edit: if, as per your comment, the issue is using a byte array as a HashMap key then see this question.


You can also use a ByteArrayComparator from Apache Directory. In addition to equals it lets you compare if one array is greater than the other.


Java byte compare,

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

Try for this:

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

I am also not sure about this, but try this may be it works.


I looked for an array wrapper which makes it comparable to use with guava TreeRangeMap. The class doesn't accept comparator.

After some research I realized that ByteBuffer from JDK has this feature and it doesn't copy original array which is good. More over you can compare faster with ByteBuffer::asLongBuffer 8 bytes at time (also doesn't copy). By default ByteBuffer::wrap(byte[]) use BigEndian so order relation is the same as comparing individual bytes.

.


You can also use org.apache.commons.lang.ArrayUtils.isEquals()


They are returning false because you are testing for object identity rather than value equality. This returns false because your arrays are actually different objects in memory.

If you want to test for value equality should use the handy comparison functions in java.util.Arrays

e.g.

import java.util.Arrays;

'''''

Arrays.equals(a,b);

Because neither == nor the equals() method of the array compare the contents; both only evaluate object identity (== always does, and equals() is not overwritten, so the version from Object is being used).

For comparing the contents, use Arrays.equals().


why a[] doesn't equals b[]? Because equals function really called on Byte[] or byte[] is Object.equals(Object obj). This functions only compares object identify , don't compare the contents of the array.


Cause they're not equal, ie: they're different arrays with equal elements inside.

Try using Arrays.equals() or Arrays.deepEquals().


Arrays.equals is not enough for a comparator, you can not check the map contain the data. I copy the code from Arrays.equals, modified to build a 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;
        }
    }
}

There's a faster way to do that:

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