10

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

Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
Jason S
  • 184,598
  • 164
  • 608
  • 970

6 Answers6

7

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;
}
esoriano
  • 477
  • 6
  • 6
4

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.

Uri
  • 88,451
  • 51
  • 221
  • 321
  • I'm curious for a case where someone would null terminate their own array in Java – matt b Jul 07 '09 at 04:07
  • I never tried that, but I would assume that maybe if one invoked a native method in C and used a buffer... – Uri Jul 07 '09 at 04:08
  • 4
    Where did strcmp come from? The question was about memcmp, and I can't see strcmp in edit histories either. – laalto Jul 07 '09 at 10:50
  • 1
    From the man page: "The memcmp() function returns an integer 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." Arrays.equals() doesn't give any indication of which is greater. – fbarber Aug 13 '13 at 12:47
3

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

lavinio
  • 23,931
  • 5
  • 55
  • 71
2

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 :-).

Roman Nikitchenko
  • 12,800
  • 7
  • 74
  • 110
0

[Arrays.equals][1]

[1]: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Arrays.html#equals(byte[], byte[])

oscarkuo
  • 10,431
  • 6
  • 49
  • 62
0

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;
}
John Calcote
  • 793
  • 1
  • 8
  • 15
  • heh - this is _functionally_ what C/C++ memcmp does. It's usually an intrinsic though - which means it's highly optimized, calling some inline assembly to use processor instructions. Imho, it's about time Java provided something like this (with sub-ranges, of course). They have system.arraycopy - why not System.bytearraycmp? When you need to compare ranges of byte arrays, you're usually doing it because you're writing code that needs to be FAST. – John Calcote Nov 20 '22 at 05:33