开发时经常存在文字占位符替换的需求,目前可以实现该功能的方法多种多样,那究竟哪种的性能最好呢?我调研了String.format的占位符替换,Hutool的CharSequenceUtil.replace的替换以及apache common.text的StringSubstitutor替换性能,用JMH进行了性能测试。
代码如下:
import cn.hutool.core.text.CharSequenceUtil;
import org.apache.commons.text.StringSubstitutor;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 整合SpringBoot基准测试
*/
@BenchmarkMode(Mode.AverageTime) // 测试方法平均执行时间
@OutputTimeUnit(TimeUnit.MICROSECONDS) // 输出结果的时间粒度为微秒
@State(Scope.Thread)
public class JMHFormatTest {
private static String CODE_BY_FORMAT = "您正在登录%s,验证码:%s(4分钟内有效)";
private static String CODE_BY_REPLACE = "您正在登录{app},验证码:{code}(4分钟内有效)";
private static String CODE_BY_SUBSTI = "您正在登录${app},验证码:${code}(4分钟内有效)";
private static final Map<String, String> valueMap = new HashMap<String, String>(){
{
put("app", "abc");
put("code", "123456");
}
};
public static Integer random()
{
int max=3,min=1;
long randomNum = System.currentTimeMillis();
return (int) (randomNum%(max-min)+min);
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder().include(JMHFormatTest.class.getSimpleName())
.warmupIterations(1).measurementIterations(5).forks(1).build();
new Runner(options).run();
}
@Setup(Level.Trial)//测试级别 执行一次
public void init() {
}
@Benchmark
@Threads(5)
public static void testFormat() {
String res = String.format(CODE_BY_FORMAT, "abc‘’", "123456");
}
@Benchmark
@Threads(5)
public static void testReplace() {
String res1 = CharSequenceUtil.replace(CODE_BY_REPLACE, "{app}", "abc");
String res = CharSequenceUtil.replace(res1, "{code}", "123456");
}
@Benchmark
@Threads(5)
public static void testStringSubstitutor() {
StringSubstitutor sub = new StringSubstitutor(valueMap);
String resolvedString = sub.replace(CODE_BY_SUBSTI);
}
}
每个方法得到的结果都是一样的,开启五个线程在多线程环境下试一下效果。
可以看到String.format的效率最低,执行一次需要0.747微秒,效率最高的是CharSequenceUtil.replace,执行一次只需要0.248微秒。因此,相关场景建议使用CharSequenceUtil.replace