好吧,实际上,想想每个数字的字符串是如何“创建”的:通过除数和 10 的模数。所以 int-to-String 转换实际上将执行您正在执行的相同任务。
这是 的源代码Integer.getChars(),它是通过调用的Integer.toString(),以及其他一些缓冲区管理:
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Generate two digits per iteration
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
如您所见,对于大于 65536 的数字,它使用并改进了除法转换循环。对于较低的数字(或者一旦原始数字被削减),就会进行一些重度优化(位移位和字节掩码)并继续进行。除法的成本通常要高得多,比位移慢大约 20 到 60 倍。所以最后一部分真的很快。但这只是5位数,那会有多大的影响呢?
还要考虑内存管理。如果您的系统在所有内核上保持 100% 运行,则 JVM 可能会遇到速度障碍,并且当(如果)可能必须发生垃圾收集时,GC 引起的“强制”暂停可能会消除所有速度优势。(测试这应该是分钟内的长期测试)。
您也可以考虑将问题/任务拆分到多个线程中。最简单的方法是使用 java 1.8-new 流。或者你有你自己的并行器/分离器和你自己的任务数组/队列。可能几乎是任务速度的 n 倍,其中 n 是您可以使用的 CPU 内核数。
正如其他人所说,实际上最好自己测试速度。最好写一个运行大约 10 秒的测试。这足够长,可以为您提供稳定的估计和 JIT 优化,并且足够短,不会无聊到地狱。
另一方面,通常最好以一种明显的、非神秘的、易于维护的方式来解决问题。所以如果我必须实现它,我会测试,如果差异小于 5 倍,我会只坚持数字。没有附加字符串:-D