Java字符串连接的多种实现方法及效率对比
JDK 1.8(Java 8)里新增String.join()方法用于字符串连接。本文基于《Java实现String.join()和效率比较》一文,分析和比较四种自定义实现与String.join()方法的效率,并纠正原文的一些错误。
代码示例如下:
public class Test {
public static void main(String[] args) {
String[] strOri = {"a","b","c","d","e","f","g","h"}; //同new string[]{"a","b","c","d","e","f","g","h"}
String strRes = ""; int loops = 100000; Date date = new Date(); for(int i = 0; i < loops; i++) {strRes = join1(strOri, ":");} date = recordTime(date, 1); //
for(int i = 0; i < loops; i++) {strRes = join2(strOri, ":");} date = recordTime(date, 2);
for(int i = 0; i < loops; i++) {strRes = join3(strOri, ":");} date = recordTime(date, 3);
for(int i = 0; i < loops; i++) {strRes = join4(strOri, ":");} date = recordTime(date, 4);
for(int i = 0; i < loops; i++) {strRes = join5(strOri, ":");} date = recordTime(date, 5); long startTime = System.currentTimeMillis(); //
for(int i = 0; i < loops; i++) {strRes = join5(strOri, ":");}
long endTime = System.currentTimeMillis(); System.out.println("5c:{" + strRes + "} costs " + (endTime-startTime) + "ms"); startTime = System.nanoTime();
for(int i = 0; i < loops; i++) {strRes = join5(strOri, ":");}
endTime = System.nanoTime(); System.out.println("5n:{" + strRes + "} costs " + (endTime-startTime) + "ns");
} private static void recordTime_Wrong(Date date, int no) {
System.out.println(no + ": costs " + (new Date().getTime()-date.getTime()) + "ms");
date = new Date();
}
private static Date recordTime(Date date, int no) {
System.out.println(no + ": costs " + (new Date().getTime()-date.getTime()) + "ms");
return new Date();
} private static String join1(String[] strOri, String delimiter) {
StringBuffer sb = new StringBuffer(); //
for(String s : strOri) {
sb.append(s+delimiter); //
}
return sb.toString().substring(0, sb.toString().length()-1);
} private static String join2(String[] strOri, String delimiter) {
StringBuffer sb = new StringBuffer();
for(String s : strOri) {
sb.append(s+delimiter);
}
String s = sb.toString();
return s.substring(0, s.length()-1);
} private static String join3(String[] strOri, String delimiter) {
StringBuffer sb = new StringBuffer();
for(int i = 0; i < strOri.length; i++) {
if (i != strOri.length-1) {
sb.append(strOri[i]+delimiter);
} else {
sb.append(strOri[i]);
}
}
return sb.toString();
} private static String join4(String[] strOri, String delimiter) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < strOri.length-1; i++) {
stringBuilder.append(strOri[i]).append(delimiter);
}
stringBuilder.append(strOri[strOri.length-1]);
return stringBuilder.toString();
} private static String join5(String[] strOri, String delimiter) {
return String.join(delimiter, strOri); //
}
}
选取三次运行输出结果如下:
1: costs 930ms
2: costs 902ms
3: costs 637ms
4: costs 230ms
5: costs 364ms
5c:{a:b:c:d:e:f:g:h} costs 413ms
5n:{a:b:c:d:e:f:g:h} costs 286466296ns
1: costs 834ms
2: costs 788ms
3: costs 576ms
4: costs 248ms
5: costs 350ms
5c:{a:b:c:d:e:f:g:h} costs 384ms
5n:{a:b:c:d:e:f:g:h} costs 283256112ns
1: costs 774ms
2: costs 728ms
3: costs 605ms
4: costs 297ms
5: costs 417ms
5c:{a:b:c:d:e:f:g:h} costs 280ms
5n:{a:b:c:d:e:f:g:h} costs 279838638ns
可见,join4()执行最快,其次是join5()。join1()和join2()执行效率接近,前者调用两次toString(),故效率略低。
总结如下:
1. 原文recordTime(即本文recordTime_Wrong)方法中,无法通过"date = new Date()"修改外部的date引用(根因详见《java中的传值与传引用》)。这会导致每次调用recordTime()时,起始时间始终是"Date date = new Date()"获得的对象(表现为join*耗时递增)。
2. 查看Java源码可知,new Date()其实就是调用System.currentTimeMillis():
public Date() {
this(System.currentTimeMillis()); //相当于Date(System.currentTimeMillis())
}
可以使用new Date().getTime()获取当前时间戳(毫秒)。注意,该毫秒数一般以1970-01-01 00:00:00为参考点,但东八区要加上时区,即以1970-01-01 08:00:00为参考时间。此外,通过getTime()获取毫秒数效率不如System.currentTimeMillis(),后者返回自1970年1月1日0时起的毫秒数。
System.nanoTime()的计时精度不保证一定高于System.currentTimeMillis(),但可保证数值递增(后者相减时可能产生负值)。
若要对代码进行更准确的计时,可参考《How do I write a correct micro-benchmark in Java?》一文。
3. StringBuffer对象是线程安全的,其方法都是同步的(synchronized)。临时变量应使用StringBuilder(效率更高),避用StringBuffer。
4. 在循环内部,不要使用append(a+b)的形式,而应改为append(a).append(b)。
5. String.join()内部使用StringBuilder实现,因此join5()性能接近join4()。当然,String.join()的功能比join4()更多。
Java字符串连接的多种实现方法及效率对比的更多相关文章
- python字符串连接的三种方法及其效率、适用场景详解
python字符串连接的方法,一般有以下三种:方法1:直接通过加号(+)操作符连接website=& 39;python& 39;+& 39;tab& 39;+& ...
- Java字符串比较(3种方法)以及对比 C++ 时的注意项
字符串比较是常见的操作,包括比较相等.比较大小.比较前缀和后缀串等.在 Java 中,比较字符串的常用方法有 3 个:equals() 方法.equalsIgnoreCase() 方法. compar ...
- Python字符串连接的5种方法
总结了一下Python字符串连接的5种方法: 加号 第一种,有编程经验的人,估计都知道很多语言里面是用加号连接两个字符串,Python里面也是如此直接用 "+" 来连接两个字符串: ...
- java字符串格式化:String.format()方法的使用
转自:http://kgd1120.iteye.com/blog/1293633 常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的读者应 ...
- Java字符串连接操作的性能问题
首先,看一段实验程序: package com.test; class StringTest { public static void main(String[] args) { long start ...
- C#三种字符串拼接方法的效率对比
C#字符串拼接的方法常用的有:StringBuilder.+.string.Format.List<string>.使用情况不同,效率不同. 1.+的方式 string sql = &qu ...
- Java字符串连接最佳实践
一个小问题,分享给大家. + 操作和 StringBuilder 都能连接字符串,使用+来拼接字符串,使用javap命令来反编译代码,可以看出实际上编译器会自动创建StringBuilder,调用它的 ...
- 理解Java字符串常量池与intern()方法
String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo ...
- Java字符串的split(String str)方法空串的问题
String strs[] = "SS1BB2CC3".split("\\D+"); public static String Test(){ Date d = ...
随机推荐
- Set集合架构和常用实现类的源码分析以及实例应用
说明:Set的实现类都是基于Map来实现的(HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的). (01) Set 是继承于Collection的接口.它是一个不允许 ...
- 基于zookeeper的高可用Hadoop HA集群安装
(1)hadoop2.7.1源码编译 http://aperise.iteye.com/blog/2246856 (2)hadoop2.7.1安装准备 http://aperise.iteye.com ...
- 使用python实现深度神经网络 3(转)
使用python实现深度神经网络 3 快速计算梯度的魔法--反向传播算法 快速计算梯度的魔法--反向传播算法 一.实验介绍 1.1 实验内容 第一次实验最后我们说了,我们已经学习了深度学习中的模型mo ...
- 柳青(Jean)英文演讲集合
1.Didi Chuxing's Jean Liu on The Future of Cities https://www.youtube.com/watch?v=G9uPGoN0dvQ 2.Did ...
- idea 集成sonarLint检查代码bugs
1.目标 idea集成sonar的代码检查,实现可以在提交代码前就检查你的代码,而不是将代码提交之后,之后再去检查. Sonar可以从以下七个维度检测代码质量,而作为开发人员至少需要处理前5种代码质量 ...
- SSE图像算法优化系列二十八:深度优化局部拉普拉斯金字塔滤波器。
基于局部拉普拉斯金字塔的Edge-aware滤波器是在2011年由Adobe 公司的研究员Sylvain Paris(大神级人物,写了很多文章)提出的,我在4年前曾经参考有关代码实现过这个算法,但是速 ...
- C语言结构体变量私有化
操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 问题描述 C语言结构体定义中的变量默认是公有(Public)属性,如果实现成员变量的私有(Private)化? 解决方案 ...
- 升级SilverLight为5.1.50907.0后,VS调试时报“无法启动调试--未安装 Silverlight Developer 运行时。请安装一个匹配版本”的处理办法
作者: zyl910 一.问题 今天需要调试一个SilverLight程序.运行时ie弹出了一个升级提示,于是手贱点了升级. 随后便悲剧了,VS调试时报"无法启动调试--未安装 Silver ...
- mysql官方驱动jar
问题描述: 在mysql5.7版本,发现登录不了,找不到原因.有人说是驱动的问题,下载最新的驱动,问题得到解决! 问题解决: 下载最新mysql-jar驱动,传统版本最新mysql-jar驱动版本5. ...
- Adroid动态加载Apk-插件化技术框架(动态代理方案)
技术:Android + java +动态加载+插件化 概述 为什么要使用插件化?在开发中,一个项目只会越做越大.初始版本可能是单一功能,后续可能加上各种风马牛不相及的功能.所以我认为插件化可以使 ...