@Malt 的回答肯定突出了您的代码的问题:它不会 0 填充 int 十六进制值;并且您使用a & 0xff 将 int 屏蔽为仅获取最后 8 位。您最初的问题意味着您只是在每个int 中的最后一个byte 之后,但这真的不清楚。
您说您每秒都从远程对象获得结果。在具有大型数组的慢速机器上,使用您的方法(或者更确切地说是 Malt 的更正版本)方法将长 int[] 转换为十六进制字符串可能需要大量毫秒。
更快的方法是使用位移从每个 int 中获取每个 4 位 nibble,并从静态十六进制查找数组中获取适当的十六进制字符(请注意,这会进行 base-16 编码,您会从 base-64 编码得到更短的字符串):
public class AltConverter {
final protected static char[] encoding = "0123456789ABCDEF".toCharArray();
public String convertToString(int[] arr) {
char[] encodedChars = new char[arr.length * 4 * 2];
for (int i = 0; i < arr.length; i++) {
int v = arr[i];
int idx = i * 4 * 2;
for (int j = 0; j < 8; j++) {
encodedChars[idx + j] = encoding[(v >>> ((7-j)*4)) & 0x0F];
}
}
return new String(encodedChars);
}
}
使用 caliper(微基准测试 results here)与您的原始方法进行测试表明,这大约快 11 倍 †(警告:在我的机器上)。 编辑对于任何有兴趣运行它并比较结果的人,有一个带有源代码的gist here。
即使是单个元素数组
最初的微基准测试使用Caliper,因为我当时碰巧在尝试。我已将其重写为使用JMH。这样做时,我发现 results I linked to 并在此处复制最初使用了一个数组,该数组只为每个 int 元素填充了 0。这导致 JVM 为长度 > 1 的数组优化了 AltConverter 代码,从而在 AltConverter 与 SimpleConverter 中产生了 10 到 11 倍的人为改进。 JMH 和 Caliper 对有缺陷的和已修正的基准产生了非常相似的结果。 (更新了maven eclipse的基准项目here)。
这大约快 2 到 4 倍,具体取决于数组长度(在我的机器上™)。平均运行时结果(以 ns 为单位)为:
以纳秒为单位的平均运行时间
原始方法:SimpleConverter
新方法:AltConverter
| N | Alt / ns |错误/ns |简单/ns |错误/ns |
加速 |
| ---------: | ---------: | ---------: | ----------: | ---------: | --------: |
| 1 | 30 | 1 | 61 | 2 |
2.0x |
| 100 |第852章19 | 3,724 | 99 |
4.4 倍 |
| 1000 | 7,517 | 200 | 36,484 |第879章
4.9 倍 |
| 1000,0 | 82,641 | 1,416 | 360,670 | 5,728 |
4.4 倍 |
| 1000,00 | 1,014,612 | 241,089 | 4,006,940 | 91,870 |
3.9 倍 |
| 1000,000 | 9,929,510 | 174,006 | 41,077,214 | 1,181,322 |
4.1x |
| 1000,000,0 | 182,698,229 | 16,571,654 | 432,730,259 | 13,310,797 |
2.4 倍 |
†免责声明:在现实世界的应用程序中依赖微基准测试作为性能指标是危险的,但 caliper 是一个很好的基准测试框架,jmh 更好。 10x 4x 的性能差异,非常小的标准偏差,以 caliper 为单位,良好的 t 检验结果足以表明即使在更复杂的应用程序中也有良好的性能提升。