Java - 检查String大小的最快方法

时间:2017-04-24 11:12:43

标签: java utf-8 java-8

我在循环语句中有以下代码 在循环中,字符串被附加到sb(StringBuilder)并检查sb的大小是否已达到5MB。

if (sb.toString().getBytes("UTF-8").length >= 5242880) {
    // Do something
}

这种方法很好,但速度很慢(在检查尺寸方面)
最快的方法是什么?

3 个答案:

答案 0 :(得分:10)

您可以使用

快速计算UTF-8长度
public static int utf8Length(CharSequence cs) {
    return cs.codePoints()
        .map(cp -> cp<=0x7ff? cp<=0x7f? 1: 2: cp<=0xffff? 3: 4)
        .sum();
}

如果ASCII字符在内容中占主导地位,则使用

可能会稍快一些
public static int utf8Length(CharSequence cs) {
    return cs.length()
         + cs.codePoints().filter(cp -> cp>0x7f).map(cp -> cp<=0x7ff? 1: 2).sum();
}

代替。

但您也可以考虑不重新计算整个尺寸的优化潜力,但只考虑您要附加到StringBuilder的新片段的大小,类似

    StringBuilder sb = new StringBuilder();
    int length = 0;
    for(…; …; …) {
        String s = … //calculateNextString();
        sb.append(s);
        length += utf8Length(s);
        if(length >= 5242880) {
            // Do something

            // in case you're flushing the data:
            sb.setLength(0);
            length = 0;
        }
    }

这假设如果你附加包含代理对的片段,它们总是完整的并且不会被分成两半。对于普通应用,情况应始终如此。

Didier-L建议的另一种可能性是推迟计算,直到你的StringBuilder达到阈值的长度除以3,如前所述,不可能有{{1}长度大于阈值。但是,只有在某些执行中没有达到UTF-8时才会有用。

答案 1 :(得分:8)

如果循环1000次,则会生成1000String,然后转换为“UTF-8 Byte”数组,以获得长度。

我会通过存储第一个长度来减少转换。然后,在每个循环上,只获取添加值的长度,然后这只是一个补充。

int length = sb.toString().getBytes("UTF-8").length;
for(String s : list){
    sb.append(s);
    length += s.getBytes("UTF-8").length;
    if(...){
    ...
    }
}

这会减少使用的内存和转换成本

答案 2 :(得分:2)

考虑使用ByteArrayOutputStream和OutputStreamWriter而不是StringBuilder。使用ByteArrayOutputStream.size()来测试大小。