我需要比较2字节数组并知道哪一个更大或者它们是否相等(只是相等或不同是不够的)。 字节数组表示15个字符或更多字符的String值。 我的代码中重复了这种比较。
我想通过在Java中使用等效的C ++ memcmp方法来改进再见数组比较(希望通过JNI)。 我找到了一个在C#中使用DLLImport的例子,所以我希望也可以应用JNI调用。
以下是C#代码段:
[DllImport("msvcrt.dll")]
unsafe static extern int memcmp(void* b1, void* b2, long count);
unsafe static int ByteArrayCompare1(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length)
{
CompareCount++;
fixed (byte* p1 = b1)
fixed (byte* p2 = b2)
{
int cmp = memcmp(p1 + b1Index, p2 + b2Index, Math.Min(b1Length, b2Length));
if (cmp == 0)
{
cmp = b1Length.CompareTo(b2Length);
}
return cmp;
}
}
有谁知道如何在Java中实现它?
提前致谢,
黛安娜
答案 0 :(得分:2)
您确定您的代码在这些比较上花费了大量时间吗?我建议现在调用Java函数,然后计时;如果你仍然需要,你可以添加JNI / JNA。
请记住,通过添加JNI,您可以显着增加出错的可能性,并且只将程序限制为编译库的体系结构。
答案 1 :(得分:0)
您可以使用JNI,但Java在JNI上有一个名为JNA (Java Native Access)的变体,它允许您直接访问共享库而无需在其周围缠绕JNI接口,因此您可以使用它直接访问memcmp
:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
public class Test {
public interface CStdLib extends Library {
int memcmp(Pointer s1, Pointer s2, int n);
}
public static void main(String[] args) {
CStdLib c = (CStdLib)Native.loadLibrary("msvcrt", CStdLib.class);
c.memcmp(...);
}
}
我没有测试过上述内容,我对memcmp
签名没有特别的确认,因为它需要void*
和size_t
,两者都没有明显的Java等价物,但其中的一些变体应该可以正常工作
(署名:我从another answer of mine中提取了一些JNA信息)
答案 2 :(得分:0)
只需使用以下代码,看看它是否足够快。
package so3883485;
import java.util.concurrent.atomic.AtomicLong;
public class ByteArrayUtils {
static final AtomicLong COMPARE_COUNT = new AtomicLong(0);
public static int compare(byte[] b1, int b1Index, int b1Length, byte[] b2, int b2Index, int b2Length) {
COMPARE_COUNT.incrementAndGet();
final int commonLength = Math.min(b1Length, b2Length);
for (int i = 0; i < commonLength; i++) {
final byte byte1 = b1[b1Index + i];
final byte byte2 = b2[b2Index + i];
if (byte1 != byte2) {
return (byte1 < byte2) ? -1 : 1;
}
}
if (b1Length != b2Length) {
return (b1Length < b2Length) ? -2 : 2;
}
return 0;
}
}
进行一些单元测试,以确保基本案例按预期工作。
package so3883485;
import static org.junit.Assert.*;
import static so3883485.ByteArrayUtils.*;
import org.junit.Test;
public class ByteArrayUtilsTest {
@Test
public void test() {
byte[] bytes = { 1, 2, 3, 4, 5 };
assertEquals(0, compare(bytes, 0, bytes.length, bytes, 0, bytes.length));
assertEquals(0, compare(bytes, 0, 0, bytes, 0, 0));
assertEquals(-2, compare(bytes, 0, 0, bytes, 0, 1));
assertEquals(2, compare(bytes, 0, 1, bytes, 0, 0));
assertEquals(-1, compare(bytes, 1, 1, bytes, 2, 1));
assertEquals(1, compare(bytes, 2, 1, bytes, 1, 1));
}
}