在Java中对字符串的操作可以说是最常用的,在对字符串的操作中有三种拼接字符串的方法,下面我们来看看这三种方式有何不同,在什么时候用比较合适。
先来看一段代码:
package com.codeing.snail.test; public class StringFormat { private static long startPointTime; public static void main(String[] args) { String s1 = "小明"; String s2 = "和"; String s3 = "小强"; String s4 = "一起LOL"; startPointTime = System.currentTimeMillis(); strFormat2(s1, s2); printTimeAndClear(); strFormat1(); printTimeAndClear(); strFormat3(s1, s2, s3, s4); printTimeAndClear(); } private static String strFormat3(String s1, String s2, String s3, String s4) { StringBuilder sb = new StringBuilder(); sb.append(s1); sb.append(s2); sb.append(s3); sb.append(s4); return sb.toString(); } private static String strFormat2(String s1, String s2) { return s1 + "和" + s2 + "一起LOL"; } private static String strFormat1() { return String.format("%s和%s一起LOL", new String[]{ "小明", "小强"}); } private static void printTimeAndClear() { System.out.println(System.currentTimeMillis() - startPointTime); startPointTime = System.currentTimeMillis(); } }输出结果:
从上面的结果我们可以看出,在拼接字符串的时候使用format方式比较耗时,但是这样就得出结论还太早,下面我们来循环1000次看一下。
package com.codeing.snail.test; public class StringFormat { private static long startPointTime; public static void main(String[] args) { String s1 = "小明"; String s2 = "和"; String s3 = "小强"; String s4 = "一起LOL"; startPointTime = System.currentTimeMillis(); strFormat2(s1, s2); printTimeAndClear(); //strFormat1(); //printTimeAndClear(); strFormat3(s1, s2, s3, s4); printTimeAndClear(); } private static String strFormat3(String s1, String s2, String s3, String s4) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < 1000; i++){ sb.append(String.valueOf(i)); } return sb.toString(); } private static String strFormat2(String s1, String s2) { String str = "begin"; for(int i = 0; i < 1000; i++){ str = str + String.valueOf(i); } return str; } private static String strFormat1() { String str = "begin"; String[] strArr = new String[1000]; for(int i = 0; i < strArr.length; i++){ strArr[i] = String.valueOf(i); } //我勒个去,这不会让我写1000个他匹配符吧。。。显然这种方式不适合大量的拼接。 //return String.format("%s%s%s......", strArr); return str; } private static void printTimeAndClear() { System.out.println(System.currentTimeMillis() - startPointTime); startPointTime = System.currentTimeMillis(); } }输出结果:
上面是用“+”号拼接字符串的结果,下面是使用StringBuilder的结果,很显然在拼接很频繁的情况下使用StringBuilder比使用“+”号拼接好,这种情况下使用format可以不予考虑。
综合比较:StringBuilder胜出,如果拼接的字符串比较多则可以优先考虑耗时。
public AbstractStringBuilder append(String str) { if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; return this; }其中value是一个char[]类型,我们可以大概了解到实现字符串拼接的原理是字符数组的拷贝操作实现的。其实两个字符串相加的本质也是StringBuilder的方式相加的,但是会创建多余的字符串对象。
public static String format(String format, Object... args) { return new Formatter().format(format, args).toString(); }java.util.Formatter这个类可能大家比较熟悉,这个是格式化文本输出的类,比如日期、金额等,我们最常见的System.out.println()也是通过调用此类的format方法实现的。
public Formatter() { this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder()); }
/* Private constructors */ private Formatter(Locale l, Appendable a) { this.a = a; this.l = l; this.zero = getZero(l); }可以看到创建了一个StringBuilder作为了Formatter的全局变量。
public Formatter format(Locale l, String format, Object ... args) { ensureOpen(); // index of last argument referenced int last = -1; // last ordinary index int lasto = -1; FormatString[] fsa = parse(format); for (int i = 0; i < fsa.length; i++) { FormatString fs = fsa[i]; int index = fs.index(); try { switch (index) { case -2: // fixed string, "%n", or "%%" fs.print(null, l); break; case -1: // relative index if (last < 0 || (args != null && last > args.length - 1)) throw new MissingFormatArgumentException(fs.toString()); fs.print((args == null ? null : args[last]), l); break; case 0: // ordinary index lasto++; last = lasto; if (args != null && lasto > args.length - 1) throw new MissingFormatArgumentException(fs.toString()); fs.print((args == null ? null : args[lasto]), l); break; default: // explicit index last = index - 1; if (args != null && last > args.length - 1) throw new MissingFormatArgumentException(fs.toString()); fs.print((args == null ? null : args[last]), l); break; } } catch (IOException x) { lastException = x; } } return this; }在format方法中我们看到一个FormatString的print方法如下:
public void print(Object arg, Locale l) throws IOException { a.append(s); }a就是我们上面创建的StringBuilder,这下我们就明白了,原来String.format也是通过StringBuilder来时实现的。