Java字符串模板格式化汇总8法(附性能对比)

原创
2017/07/25 03:25
阅读数 1.2W

Table of Contents

在开发过程中,经常会和字符串打交道, 其中字符串拼接的工作必不可少,

比如:

我要生成一个如此格式的路径,有什么办法?

String path= "/home/expressdelivery/${yearMonth}/${expressDeliveryType}/vipQuery_${fileName}.log";

其中的:

yearMonth

是当前日期的年月

expressDeliveryType

是物流方式的类型,以顺丰sf举例 ,如果是其他快递会是其他值

fileName

是当前时间的时间戳

我们来汇总下实现方式

1. ++

对于初学JAVA的蒙童,大约都会使用这招

@Test
public void testAdd(){

    Date now = new Date();

    String yearMonth = DateUtil.toString(now, DatePattern.YEAR_AND_MONTH);
    String expressDeliveryType = "sf";
    String fileName = DateUtil.toString(now, DatePattern.TIMESTAMP);

    String template = "/home/expressdelivery/" + yearMonth + "/" + expressDeliveryType + "/vipQuery_" + fileName + ".log";

    System.out.println(template);
}

输出 :

/home/expressdelivery/2017-07/sf/vipQuery_20170723042314.log

2. StringBuffer / StringBuilder

@Test
public void testStringBuilder(){

    Date now = new Date();

    String yearMonth = DateUtil.toString(now, DatePattern.YEAR_AND_MONTH);
    String expressDeliveryType = "sf";
    String fileName = DateUtil.toString(now, DatePattern.TIMESTAMP);

    StringBuilder sb = new StringBuilder();
    sb.append("/home/expressdelivery/");
    sb.append(yearMonth);
    sb.append("/");
    sb.append(expressDeliveryType);
    sb.append("/vipQuery_");
    sb.append(fileName);
    sb.append(".log");

    String template = sb.toString();

    System.out.println(template);
}

输出 :

/home/expressdelivery/2017-07/sf/vipQuery_20170723042603.log

缺点:

  • 代码太长了

3. StringUtil.format(String, Object…​)

使用 com.feilong.core.lang.StringUtil.format(String, Object…​)

内部封装了 String.format(String, Object)

@Test
public void testStringFormat(){
    Date now = new Date();

    String yearMonth = DateUtil.toString(now, DatePattern.YEAR_AND_MONTH);
    String expressDeliveryType = "sf";
    String fileName = DateUtil.toString(now, DatePattern.TIMESTAMP);

    String template = StringUtil.format("/home/expressdelivery/%s/%s/vipQuery_%s.log", yearMonth, expressDeliveryType, fileName);

    System.out.println(template);
}

输出 :

/home/expressdelivery/2017-07/sf/vipQuery_20170723043153.log

4. MessageFormatUtil.format(String, Object…​)

使用 com.feilong.core.text.MessageFormatUtil.format(String, Object…​)

内部封装了 java.text.MessageFormat.format(String, Object…​)

@Test
public void testMessageFormat(){
    Date now = new Date();

    String yearMonth = DateUtil.toString(now, DatePattern.YEAR_AND_MONTH);
    String expressDeliveryType = "sf";
    String fileName = DateUtil.toString(now, DatePattern.TIMESTAMP);

    String template = MessageFormatUtil
                    .format("/home/expressdelivery/{0}/{1}/vipQuery_{2}.log", yearMonth, expressDeliveryType, fileName);

    System.out.println(template);
}

输出 :

/home/expressdelivery/2017-07/sf/vipQuery_20170723043153.log

5. Slf4jUtil.format(String, Object…​)

使用 com.feilong.tools.slf4j.Slf4jUtil.format(String, Object…​)

借助 slf4j 日志占位符

@Test
public void testSlf4jFormat(){
    Date now = new Date();

    String yearMonth = DateUtil.toString(now, DatePattern.YEAR_AND_MONTH);
    String expressDeliveryType = "sf";
    String fileName = DateUtil.toString(now, DatePattern.TIMESTAMP);

    String template = Slf4jUtil.format("/home/expressdelivery/{}/{}/vipQuery_{}.log", yearMonth, expressDeliveryType, fileName);

    System.out.println(template);
}

输出:

/home/expressdelivery/2017-07/sf/vipQuery_20170723144236.log

6. StringUtil.replace(CharSequence, Map<String, V>)

使用 com.feilong.core.lang.StringUtil.replace(CharSequence, Map<String, V>)

内部封装了 apache commons-lang3 org.apache.commons.lang3.text.StrSubstitutor , 现在叫 commons-text

使用给定的字符串 templateString 作为模板,解析匹配的变量 .

@Test
public void testReplace(){
    Date date = new Date();
    Map<String, String> map = new HashMap<>();
    map.put("yearMonth", DateUtil.toString(date, YEAR_AND_MONTH));
    map.put("expressDeliveryType", "sf");
    map.put("fileName", DateUtil.toString(date, TIMESTAMP));

    String template = StringUtil.replace("/home/expressdelivery/${yearMonth}/${expressDeliveryType}/vipQuery_${fileName}.log", map);

    System.out.println(template);
}

输出:

/home/expressdelivery/2017-07/sf/vipQuery_20170723144608.log

优点:

  • 模块可以定义变量名字了,不怕混乱

Note

此方法只能替换字符串,而不能像el表达式一样使用对象属性之类的来替换

7. VelocityUtil.parseString(String, Map<String, ?>)

使用 com.feilong.tools.velocity.VelocityUtil.parseString(String, Map<String, ?>)

该方法需要 jar

<dependency>
  <groupId>com.feilong.platform.tools</groupId>
  <artifactId>feilong-tools-velocity</artifactId>
  <version>${version.feilong-platform}</version>
</dependency>
@Test
public void testVelocityParseString(){
    Date date = new Date();

    Map<String, String> map = new HashMap<>();
    map.put("yearMonth", DateUtil.toString(date, YEAR_AND_MONTH));
    map.put("expressDeliveryType", "sf");
    map.put("fileName", DateUtil.toString(date, TIMESTAMP));

    VelocityUtil velocityUtil = new VelocityUtil();

    String template = velocityUtil
                    .parseString("/home/expressdelivery/${yearMonth}/${expressDeliveryType}/vipQuery_${fileName}.log", map);

    System.out.println(template);
}

输出

/home/expressdelivery/2017-07/sf/vipQuery_20170723145856.log

8. VelocityUtil.parseTemplateWithClasspathResourceLoader(String, Map<String, ?>)

使用 com.feilong.tools.velocity.VelocityUtil.parseTemplateWithClasspathResourceLoader(String, Map<String, ?>)

该方法需要 jar

<dependency>
  <groupId>com.feilong.platform.tools</groupId>
  <artifactId>feilong-tools-velocity</artifactId>
  <version>${version.feilong-platform}</version>
</dependency>

该方法适合于 字符串模板独立成文件, 方便维护

路径是classpath 下面, 比如 velocity/path.vm

28497395 a52f617c 6fb8 11e7 9902 66249985242a

此时代码需要如此调用:

@Test
public void testVelocityParseTemplateWithClasspathResourceLoader(){
    Date date = new Date();

    Map<String, String> map = new HashMap<>();
    map.put("yearMonth", DateUtil.toString(date, YEAR_AND_MONTH));
    map.put("expressDeliveryType", "sf");
    map.put("fileName", DateUtil.toString(date, TIMESTAMP));

    VelocityUtil velocityUtil = new VelocityUtil();

    String template = velocityUtil.parseTemplateWithClasspathResourceLoader("velocity/path.vm", map);

    System.out.println(template);
}

输出 :

/home/expressdelivery/2017-07/sf/vipQuery_20170723150443.log

9. 性能对比

28501853 87f4c8c2 7017 11e7 99db 3b2d47c803a8

上图是 分别循环 100000, 500000, 1000000, 2000000 统计出来的数据

在性能上 String format 是最差的

字符串 ++ 最快, StringBuilder 次之 , slf4j 的格式化再次之

测试硬件概览:

型号名称:	MacBook Pro
处理器名称:	Intel Core i5
处理器速度:	2.9 GHz
内存:	16 GB

10. 参考

展开阅读全文
打赏
2
5 收藏
分享
加载中
在Kotlin下字符串拼接就不是问题了,天然支持变量插值
2017/12/27 09:46
回复
举报
更多评论
打赏
1 评论
5 收藏
2
分享
返回顶部
顶部