首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >快速将包含ascii字符串的byte[]转换为int/double/date等,而无需新字符串

快速将包含ascii字符串的byte[]转换为int/double/date等,而无需新字符串
EN

Stack Overflow用户
提问于 2012-02-07 15:21:20
回答 4查看 2.4K关注 0票数 1

我得到修复消息字符串(ASCII)作为ByteBuffer。我解析标记值对,并将值作为原始对象存储在树映射中,并将标记作为键。因此,我需要根据类型将date值转换为int/double/ byte[]等。

最简单的方法是创建新字符串并将其传递给标准转换器函数。例如:

代码语言:javascript
运行
复制
int convertToInt(byte[] buffer, int offset, int length)
{
  String valueStr = new String(buffer, offset, length);
  return Integer.parseInt(valueStr);
}

我知道在Java中,创建新对象是非常便宜的,还是有办法将这个ascii byte[]直接转换成原语类型的。我尝试了手写函数来做这件事,但发现它很耗时,并且没有带来更好的性能。

有没有第三方库可以做到这一点,最重要的是,这是值得做的吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-07 15:40:29

最重要的是它值得去做吗?

几乎可以肯定不是-而且在采取重大努力缓解它之前,您应该采取措施检查这是否是一个性能瓶颈。

你现在的表现怎么样?它需要是什么?(“越快越好”不是一个好的目标,否则你永远不会停下来--什么时候你可以说你“完成”了。)

分析代码--字符串创建真的有问题吗?检查你进行垃圾收集的频率等(同样,使用分析器)。

每种解析类型可能具有不同的特征。例如,对于解析整数,如果你发现在很大程度上你得到了一个数字,你可能想要在特殊情况下:

代码语言:javascript
运行
复制
if (length == 1)
{
    char c = buffer[index];
    if (c >= '0' && c <= '9')
    {
        return c - '0';
    }
    // Invalid - throw an exception or whatever
}

..。但是在你走上这条路之前,检查一下这种情况发生的频率。对从未实际出现的特定优化应用大量检查会适得其反。

票数 3
EN

Stack Overflow用户

发布于 2013-09-20 11:52:11

然而,在处理许多修复消息时,这很快就会积累起来,这一点同意Jon的观点。下面的方法将允许使用空格填充的数字。如果你需要处理小数,那么代码会稍有不同。两种方法之间的速度差异是11倍。ConvertToLong结果为0 GC。下面的代码是c#格式的:

代码语言:javascript
运行
复制
///<summary>
///Converts a byte[] of characters that represent a number into a .net long type. Numbers can be padded from left
/// with spaces.
///</summary>
///<param name="buffer">The buffer containing the number as characters</param>
///<param name="startIndex">The startIndex of the number component</param>
///<param name="endIndex">The EndIndex of the number component</param>
///<returns>The price will be returned as a long from the ASCII characters</returns>
public static long ConvertToLong(this byte[] buffer, int startIndex, int endIndex)
{
    long result = 0;
    for (int i = startIndex; i <= endIndex; i++)
    {
        if (buffer[i] != 0x20)
        {
            // 48 is the decimal value of the '0' character. So to convert the char value
            // of an int to a number we subtract 48. e.g '1' = 49 -48 = 1
            result = result * 10 + (buffer[i] - 48);
        }
    }
    return result;
}

/// <summary>
/// Same as above but converting to string then to long
/// </summary>
public static long ConvertToLong2(this byte[] buffer, int startIndex, int endIndex)
{
    for (int i = startIndex; i <= endIndex; i++)
    {
        if (buffer[i] != SpaceChar)
        {
            return long.Parse(System.Text.Encoding.UTF8.GetString(buffer, i, (endIndex - i) + 1));
        }
    }
    return 0;
}

[Test]
public void TestPerformance(){
    const int iterations = 200 * 1000;
    const int testRuns = 10;
    const int warmUp = 10000;
    const string number = "    123400";
    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(number);

    double result = 0;
    for (int i = 0; i < warmUp; i++){
        result = buffer.ConvertToLong(0, buffer.Length - 1);
    }
    for (int testRun = 0; testRun < testRuns; testRun++){
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < iterations; i++){
            result = buffer.ConvertToLong(0, buffer.Length - 1);
        }
        sw.Stop();
        Console.WriteLine("Test {4}: {0} ticks, {1}ms, 1 conversion takes = {2}μs or {3}ns. GCs: {5}", sw.ElapsedTicks,
            sw.ElapsedMilliseconds, (((decimal) sw.ElapsedMilliseconds)/((decimal) iterations))*1000,
            (((decimal) sw.ElapsedMilliseconds)/((decimal) iterations))*1000*1000, testRun,
            GC.CollectionCount(0) + GC.CollectionCount(1) + GC.CollectionCount(2));
    }
}
RESULTS
ConvertToLong:
Test 0: 9243 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 1: 8339 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 2: 8425 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 3: 8333 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 4: 8332 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 5: 8331 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 6: 8409 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 7: 8334 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 8: 8335 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
Test 9: 8331 ticks, 4ms, 1 conversion takes = 0.02000μs or 20.00000ns. GCs: 2
ConvertToLong2:
Test 0: 109067 ticks, 55ms, 1 conversion takes = 0.275000μs or 275.000000ns. GCs: 4
Test 1: 109861 ticks, 56ms, 1 conversion takes = 0.28000μs or 280.00000ns. GCs: 8
Test 2: 102888 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 9
Test 3: 105164 ticks, 53ms, 1 conversion takes = 0.265000μs or 265.000000ns. GCs: 10
Test 4: 104083 ticks, 53ms, 1 conversion takes = 0.265000μs or 265.000000ns. GCs: 11
Test 5: 102756 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 13
Test 6: 102219 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 14
Test 7: 102086 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 15
Test 8: 102672 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 17
Test 9: 102025 ticks, 52ms, 1 conversion takes = 0.26000μs or 260.00000ns. GCs: 18
票数 2
EN

Stack Overflow用户

发布于 2012-02-07 15:28:05

看看ByteBuffer吧。它具有这样的功能,包括处理字节顺序(字节顺序)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9172402

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档