1

我必须生成一个包含类的所有数据成员的字符串。例如,如果一个类定义是

class A    
 {
   private String field1;
   private String field2;
   private String field3;
   ...
   ...
 }

然后我想生成一个按该顺序包含 field1、field2 和 field3 的字符串。但是,我想做的另一件事是确保以下规则 -

  field1 is of length 20. If it is less than 20, pad it with blank spaces.
  field2 is of length 10. If it is less than 10, pad it with blank spaces.
  field1 is of length 15. If it is less than 15, pad it with blank spaces.
  ...
  ...

我计划使用一个帮助类来构建这个字符串。我想使用 StringBuilder 来获取最终的字符串。所以我有类似的东西 -

  StringBuilder builder = new StringBuilder();

  Helper.addString(field1,20,builder);

现在这个 addString 函数的实现是我关心的。对于不同的类,这个函数将被调用数千次。所以我想让它尽可能高效。问题是,最有效的方法是什么?目前,我有以下实现 -

 public static void addString(String field, int totalLengthOfField, StringBuilder builder)
 {
    int lengthOfField = field.length();
    int numberOfBlankSpacesToPutAfterString = totalLengthOfField - lengthOfField;

    if(numberOfBlankSpacesToPutAfterString >=0)
      {
        builder.append(field);
        for(int i=1; i<= numberOfBlankSpacesToPutAfterString; i++)
          {
            builder.append(" "); // append a blank space
          }
      }
    else
      {
        // throw exception - field is longer than the maximum allowed length.
      }
 }
4

7 回答 7

4

Java 有一个Formatter类,它支持为特定字段创建具有宽度定义的字符串,就像sprintf()在 C 中一样。在内部String.format()也使用一个Formatter对象。

也就是说,Formatter并不是那么快。您最好手动将字符串附加到 aStringBuilder并使用具有不同数量空格的字符串的小缓存,以避免总是附加单个空格......

例如,如果您知道填充大小将始终小于 20 个空格,则可以只创建一个String[]包含 0、1、2... 空格的字符串的表并完全跳过循环。如果没有这样的限制,您仍然可以一次附加 20 个空格的块,直到达到必要的填充大小。

于 2012-05-17T17:50:10.783 回答
0

考虑检查 apache commons (StringUtils) 是如何实现的,他们已经遇到了和你一样的问题,并且他们已经优化了方法:

public static String rightPad(String str, int size, char padChar) {
    if (str == null) {
        return null;
    }
    int pads = size - str.length();
    if (pads <= 0) {
        return str; // returns original String when possible
    }
    if (pads > PAD_LIMIT) {
        return rightPad(str, size, String.valueOf(padChar));
    }
    return str.concat(repeat(padChar, pads));
}

public static String repeat(String str, int repeat) {
    // Performance tuned for 2.0 (JDK1.4)

    if (str == null) {
        return null;
    }
    if (repeat <= 0) {
        return EMPTY;
    }
    int inputLength = str.length();
    if (repeat == 1 || inputLength == 0) {
        return str;
    }
    if (inputLength == 1 && repeat <= PAD_LIMIT) {
        return repeat(str.charAt(0), repeat);
    }

    int outputLength = inputLength * repeat;
    switch (inputLength) {
        case 1 :
            return repeat(str.charAt(0), repeat);
        case 2 :
            char ch0 = str.charAt(0);
            char ch1 = str.charAt(1);
            char[] output2 = new char[outputLength];
            for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
                output2[i] = ch0;
                output2[i + 1] = ch1;
            }
            return new String(output2);
        default :
            StringBuilder buf = new StringBuilder(outputLength);
            for (int i = 0; i < repeat; i++) {
                buf.append(str);
            }
            return buf.toString();
    }
}
于 2012-05-17T17:59:10.327 回答
0

只要您知道所需的最大填充(20),它就相当简单。

private static String spaces = "                    "; // Whatever you need max!

// your code to compute numberOfBlankSpacesToPutAfterString

if(numberOfBlankSpacesToPutAfterString >= 0) {
    builder.append(field);
    builder.append(spaces, 0, numberOfBlankSpacesToPutAfterString);
} else {
    // Report error
}
于 2012-05-17T18:02:22.573 回答
0

有什么理由不使用String.format

于 2012-05-17T17:49:32.050 回答
0

使用静态方法

String.format("%"+numberOfBlankSpacesToPutAfterString+"s",string)'
于 2012-05-17T17:49:36.280 回答
0

我可以看到至少一项优化。改变:

 if(numberOfBlankSpacesToPutAfterString >=0)

至:

 if(numberOfBlankSpacesToPutAfterString >0)

这样,如果你有 0 个空格要添加,你就永远不会进入 for 循环。没什么大不了的,但听起来每一点都很重要。

第二件事:需要构建器对象吗?你可能正在使用

 if(numberOfBlankSpacesToPutAfterString >0)
  {
    for(int i=1; i<= numberOfBlankSpacesToPutAfterString; i++)
      {
        field +=(" "); // append a blank space
      }
  }

阅读其他人提到的内容,您可以通过添加 2 的幂的间距来进一步加快速度。

 if(numberspaces > 16)
      {field +="16spaceshere"
      numberspaces -= 16;
      }
 if(numberspaces > 8)...
 if(numberspaces > 4)...

这将把它变成最多 4 个字段操作和 4 个 numberspacestoadd 操作,总共 8 个。

于 2012-05-17T17:51:09.620 回答
0
import  com.google.common.base.Strings

foo = Strings.repeat(" ", 10)
于 2017-11-01T16:45:54.443 回答