1.使用StringBuilder
几乎所有Java代码中你都应该考虑这个问题。避免使用+号。你可能会认为StringBuilder只是个语法糖,比如:
Stringx="a"+args.length+"b";
…会编译成
0newjava.lang.StringBuilder[16]3dup4ldcString"a"[18]6invokespecialjava.lang.StringBuilder(java.lang.String)[20]9aload_0[args]10arraylength11invokevirtualjava.lang.StringBuilder.append(int):java.lang.StringBuilder[23]14ldcString"b"[27]16invokevirtualjava.lang.StringBuilder.append(java.lang.String):java.lang.StringBuilder[29]19invokevirtualjava.lang.StringBuilder.toString():java.lang.String[32]22astore_1[x]
但是之后你需要根据条件来修改字符串,会发生什么事情呢?
Stringx="a"+args.length+"b";if(args.length==1)x=x+args[0];
你现在会有第二个StringBuilder,这个StringBuilder本来没有存在的必要,它会消耗堆内存,给GC增加负担。你应该这样写:
StringBuilderx=newStringBuilder("a");x.append(args.length);x.append("b");if(args.length==1);x.append(args[0]);
关键点
在上面的例子中,显式地使用StringBuilder实例,和Java编译器隐式使用StringBuilder实例是没有关联的。但是记住,我们在N.O.P.E分支。我们在每个CPU周期对GC和为StringBuilder分配空间所产生的浪费,都会浪费NxOxP倍。
总是使用StringBuilder,不用+运算符是一个不错的规则。如果你的字符串构建起来很复杂,尽可能在多个方法间使用同一个StringBuilder。这就是你在生成复杂的SQL时jOOQ所做的事情。只有一个StringBuilder在整个SQLAST(AbstractSyntaxTree)中“游走”。
如果你还有StringBuffer引用,大声哭吧,把它们换成StringBuilder,因为你很少需要同步创建一个字符串。[注:StringBuffer与StringBuilder的区别就在于StringBuffer是线程安全的,但在同步代码中没必要使用StringBuffer,它会带来额外的性能开销。]
2.避免正则表达式正则表达式相对便宜和方便。但是如果你在N.O.P.E分支,那很糟糕了。如果你必须在计算机密集的代码段中使用正则表达式,至少把Pattern的引用缓存下来,避免每次都对其重新编译:
staticfinalPatternHEAVY_REGEX=Pattern.北京白癜风专科医院地址北京白癜风专科医院哪里好