为什么这段代码运行缓慢?

3
我有以下代码,用于将字节数组编码为十六进制字符串。
private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();
public static void WriteHexBytes(byte[] data, StringBuilder sb)
{
    char[] chars = new char[data.length*2];
    for (int i = 0; i < data.length; ++i)
    {
        chars[2*i] = HEX_CHARS[(data[i] & 0xF0) >>> 4];
        chars[2*i + 1] = HEX_CHARS[data[i] & 0x0F];
    }
    sb.append(chars);
}

for循环非常慢,在真正的设备上编码3MB的字节大约需要10秒钟。在模拟器上,它需要非常长的时间才能完成。

sb.append操作是瞬间完成的。

这正常吗?对我来说似乎非常缓慢?是什么导致了这种缓慢?

在三星Galaxy Tab 2 7.0上进行了测试。


请看这个链接:http://cloud101.eu/blog/2012/04/16/converting-a-byte-array-to-hexadecimal-in-java-and-android-2/ - itsrajesh4uguys
我的意思是,即使运行一个带有“chars[x]=0;”的循环也需要大约两秒钟??? - Dusan
使用左移操作符代替 2*i。将 2*i 表达式提取到本地变量中。 - user784540
1
类似于https://dev59.com/NGkw5IYBdhLWcg3wx9eC - nes1983
1
@Rafael:胡说八道。不要在没有适当警告的情况下散布胡言乱语:“我只是告诉你一些随意的东西,但我并不确定它是否正确。”我希望你不确定——因为你错了。 - nes1983
显示剩余3条评论
3个回答

1

我认为从Java的角度来看,并不明显有比您展示的更快的方法。Apache Common's code 稍微比您的好一点,但这只是一个模糊的猜测。

如果您需要更多信息,现在只能在您的硬件上进行微基准测试了,很抱歉 :(。

出于无聊的原因...我对您的解决方案和我刚刚想出来的方案进行了微型基准测试(临时的、非科学的),你的效果是我的两倍。这是我尝试的内容:

public static void niko(byte[] data, StringBuilder sb)
{
    for (byte element : data) {
        sb.append(toChar((element & 0xf0) >>> 4));
        sb.append(toChar(element & 0x0f));
    }
}

static char toChar(int b) {
    int offset = b < 10 ? 48 : 87;
    return (char) (b + offset);
}

如果你的代码在10MB的数据上重复100次,它只需要4秒就能完成,而我的则需要8秒。但是请记住,这非常依赖于硬件、JVM等因素。


哇!是哪种硬件或设备?你的结果比我的好了100倍以上!在我的Galaxy Tab 2 7.0上,安卓4.1版本,3MB的程序第一次运行需要5到10秒钟吗?我本来预计代码在移动设备上会慢一些,但是慢了数百倍?出了什么问题?仅仅一个简单的for循环从1到3M需要2秒钟才能完成……这个速度就像40MHz的Intel 386甚至更差。 - Dusan

0

我更喜欢将此写为注释(无法尝试在Android上是否有所不同),但我无法在注释中编写格式化代码... :-/

您可以尝试缓存一些值以避免某些调用:

int len = data.length;
char[] chars = new char[len * 2];
for (int i = 0; i < len; ++i) {
    int b = data[i] & 0xff;
    chars[2*i] = HEX_CHARS[b >>> 4];
    chars[2*i + 1] = HEX_CHARS[b & 0x0F];
}

顺便说一句:

如果返回一个字符串而不是写入 StringBuilder 是可以接受的,你也可以尝试将数据写入字节数组而不是字符数组以减少分配的内存大小,然后从字节数组中构建字符串。


0

这里有另一个建议:

public static void writeHexBytes(byte[] data, StringBuilder sb) {
    for (byte b : data) {
        sb.append(String.format("%02X", b));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接