【发布时间】:2014-10-24 10:44:15
【问题描述】:
我需要比较两个不同的 java byte[] 数组的前 n 个字节。有 Arrays equals() 函数,但它首先测试数组的长度,然后测试整个两个数组,我的数组长度不同,所以这不好。
除了手工编写自己的循环之外还有什么想法吗?
谢谢,
【问题讨论】:
-
您可以将您感兴趣的字节复制到两个新数组中并进行比较。
我需要比较两个不同的 java byte[] 数组的前 n 个字节。有 Arrays equals() 函数,但它首先测试数组的长度,然后测试整个两个数组,我的数组长度不同,所以这不好。
除了手工编写自己的循环之外还有什么想法吗?
谢谢,
【问题讨论】:
您为什么不想手动编写自己的循环?您可以只使用Arrays 复制出subset,然后再次将其用于compare:-
byte[] a1 = Arrays.copyOfRange(array1, 0, n);
byte[] a2 = Arrays.copyOfRange(array2, 0, n);
boolean equal = Arrays.equals(a1, a2);
如果效率是一个问题,那么System.arraycopy 是一种更快但更冗长的复制数组的方式。
如果效率确实是一个问题,而不是冗长,那么循环可能是最好的方法。
boolean matched = true;
for (int i=0; i<n; i++){
if (array1[i] != array2[i]) {
matched = false;
break;
}
}
这是因为您可以在看到不匹配的字节后立即停止搜索。如果第一个字节不匹配并且我们正在比较 100 字节,在第一个解决方案中,我们在后台复制 2 批 100 字节,创建两个 100 字节数组,然后比较 100 组字节,尽管它会停止第一个。在循环中,这是循环中的一次迭代,不匹配被发现、标记,然后我们就完成了。
Java 8(更新)
通过创建要比较的索引号的Stream(使用IntStream)并使用Predicate在流上执行allMatch,可以更简洁地在Java 8语法中完成与上述相同的事情比较流中每个索引处的两个数组,如下所示:-
//Both arrays must match at all indices between 0 and n
boolean matched = IntStream.range(0, n).allMatch(i -> array1[i] == array2[i]);
//...Of course if you are comparing non simple types, you would need to use equals()
【讨论】:
这是一个使用java.nio.ByteBuffer.wrap() 的更高效的解决方案,可以避免中间复制操作:
ByteBuffer.wrap(array1, 0, n).equals(ByteBuffer.wrap(array2, 0, n));
【讨论】:
您可以将每个数组的前 n 个元素复制到新数组中,然后在这些数组上使用 Arrays.equals()。
byte[] a = {1, 2, 3, 4};
byte[] b = {1, 2, 3, 4, 5, 6};
byte[] aCopy = new byte[3];
System.arraycopy(a, 0, aCopy, 0, aCopy.length);
byte[] bCopy = new byte[3];
System.arraycopy(b, 0, bCopy, 0, bCopy.length);
boolean equal = Arrays.equals(aCopy, bCopy);
冗长,但它会做你想做的事。或者,只需从 0..n
循环boolean equal = true;
for (int i = 0; equal && i < 3; i++) {
equal = a[i] == b[i];
}
【讨论】: