equivalent of memcmp() in Java?
Asked Answered
L

6

10

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

Lavonna answered 7/7, 2009 at 2:29 Comment(0)
P
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.

Parrnell answered 7/7, 2009 at 2:31 Comment(4)
I'm curious for a case where someone would null terminate their own array in JavaDeciduous
I never tried that, but I would assume that maybe if one invoked a native method in C and used a buffer...Parrnell
Where did strcmp come from? The question was about memcmp, and I can't see strcmp in edit histories either.Marta
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.Kareem
V
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;
}
Vesica answered 7/9, 2013 at 20:26 Comment(1)
Aren't the return 1 and return -1 reversed?Gulley
P
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.

Parrnell answered 7/7, 2009 at 2:31 Comment(4)
I'm curious for a case where someone would null terminate their own array in JavaDeciduous
I never tried that, but I would assume that maybe if one invoked a native method in C and used a buffer...Parrnell
Where did strcmp come from? The question was about memcmp, and I can't see strcmp in edit histories either.Marta
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.Kareem
S
4

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

Stereotype answered 7/7, 2009 at 2:47 Comment(0)
B
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 :-).

Bar answered 20/5, 2013 at 13:16 Comment(2)
plus 1 for mentioning subranges. In that case one might use Arrays.copyOfRange() with Arrays.equals() but likely not efficient anyways.Twig
Arrays.equals() in Java Language version 9 and up has a variant with subrange signature.Monatomic
J
0

[Arrays.equals][1]

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

Jinnah answered 7/7, 2009 at 2:32 Comment(0)
R
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;
}
Refrigeration answered 8/1, 2019 at 19:40 Comment(1)
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.Refrigeration

© 2022 - 2024 — McMap. All rights reserved.