Question

If I have two byte[] arrays, is there a built-in function to compare them ala C's memcmp() ?

Was it helpful?

Solution

There's Arrays.equals().

I don't know whether the JVM implementation actually optimizes this if a corresponding instruction exists in the hardware, but I doubt it.

Also, if I remember my C correctly, strcmp works up to a null terminator (making it useful for C strings), The Arrays version will compare the entire array since Java programmers rarely bother with null-terminated arrays. You could easily write your own function, though, if you care about the null-terminator.

OTHER TIPS

Memcmp returns an int, less than, equal to, or greater than zero if the first n bytes of s1 is found, respectively, to be less than, to match, or be greater than the first n bytes of s2. Equals returns a boolean. It's not the same function. In addition, memcmp compares bytes as unsigned chars.

I think this could work:

public int memcmp(byte b1[], byte b2[], int sz){
    for(int i = 0; i < sz; i++){
        if(b1[i] != b2[i]){
            if(b1[i] >= 0 && b2[i] >= 0)
                return b1[i] - b2[i];
            if(b1[i] < 0 && b2[i] >= 0)
                return 1;
            if(b2[i] < 0 && b1[i] >= 0)
                return -1;
            if(b1[i] < 0 && b2[i] < 0){
                byte x1 = (byte) (256 + b1[i]);
                byte x2 = (byte) (256 + b2[i]);
                return x1 - x2;
            }
        }
    }
    return 0;
}

(edit) In fact, the 2's complement part is not necessary:

public static int memcmp(byte b1[], byte b2[], int sz){
    for(int i = 0; i < sz; i++){
        if(b1[i] != b2[i]){
            if((b1[i] >= 0 && b2[i] >= 0)||(b1[i] < 0 && b2[i] < 0))
                return b1[i] - b2[i];
            if(b1[i] < 0 && b2[i] >= 0)
                return 1;
            if(b2[i] < 0 && b1[i] >=0)
                return -1;
        }
    }
    return 0;
}

The java.util.Arrays.equals(byte[], byte[]) method is your friend.

Well, Arrays.equals() is good, but cannot compare subranges. In this case there is also path through Arrays.listOf() and later .subList() but not for primitives like byte[].

Actually there is no direct memcmp() equivalent. Here is discussion and as soon as I know it is in the same state by now (15 years). Most 'native' implementation could be achieved by my option through java.nio.ByteBuffer (wrap() method and then equals()). But it is somewhat big amount of code.

For people which fully don't understand subject: memcmp() is implemented in platform dependent way which is very efficient and nothing in Java currently approaching it. Any manual cycles are far far away in term of performance at least because of index range checks. Maybe some day people who came from embedded C / C++ will be satisfied on this topic :-).

In Java 8, and if you're OK treating bytes as unsigned values, which is what C/C++ memcmp actually does:

private static int memcmp(byte[] a, byte[] b, int sz) {
    for (int i = 0; i < sz; i++) {
        if (a[i] != b[i]) {
            return Byte.toUnsignedInt(a[i]) - Byte.toUnsignedInt(b[i]);
        }
    }
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top