Java 字符串拼接四种方式的性能比较分析
一、简单介绍
编写代码过程中,使用"+"和"contact"比较普遍,但是它们都不能满足大数据量的处理,一般情况下有一下四种方法处理字符串拼接,如下:
1、 加号"+"
2、 String的 contact()方法
3、 StringBuffer 的 append()方法
4、 StringBuilder 的 append()方法
二、测试代码参考
StringTest类
package com.jdk8.event.StringTest;
public class StringTest {
private static final int max = 100000;
public static void testPlus() {
System.out.println("************ plusTest() ************");
String str = "";
long start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
str = str + "a";
}
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println(" {str + \"a\"} cost=" + cost + " ms");
}
public static void testConcat() {
System.out.println("************ concatTest() ************");
String str = "";
long start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
str = str.concat("a");
}
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println(" {str.concat(\"a\")} cost=" + cost + " ms");
}
public static void testStringBuffer() {
System.out.println("************ StringBufferTest() ************");
long start = System.currentTimeMillis();
StringBuffer strBuffer = new StringBuffer();
for (int i = 0; i < max; i++) {
strBuffer.append("a");
}
strBuffer.toString();
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println(" {strBuffer.append(\"a\")} cost=" + cost + " ms");
}
public static void testStringBuilder() {
System.out.println("************ StringBuilderTest() ************");
long start = System.currentTimeMillis();
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < max; i++) {
strBuilder.append("a");
}
strBuilder.toString();
long end = System.currentTimeMillis();
long cost = end - start;
System.out.println(" {strBuilder.append(\"a\")} cost=" + cost + " ms");
}
}
测试类:TestMain
package com.jdk8.event.StringTest;
public class TestMain {
public static void main(String[] args){
System.out.println("执行100次时");
StringTest.testPlus();
StringTest.testConcat();
StringTest.testStringBuffer();
StringTest.testStringBuilder();
}
}
测试结果如下:
执行100次时
************ plusTest() ************
{str + "a"} cost=0 ms
************ concatTest() ************
{str.concat("a")} cost=0 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=0 ms
************ StringBuilderTest() ************
{strBuilder.append("a")} cost=0 ms
执行1000次时
************ concatTest() ************
{str.concat("a")} cost=1 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=0 ms
************ StringBuilderTest() ************
{strBuilder.append("a")} cost=0 ms
执行10000次时
************ plusTest() ************
{str + "a"} cost=99 ms
************ concatTest() ************
Disconnected from the target VM, address: '127.0.0.1:63818', transport: 'socket'
{str.concat("a")} cost=17 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=1 ms
************ StringBuilderTest() ************
{strBuilder.append("a")} cost=0 ms
执行100000次时
************ plusTest() ************
{str + "a"} cost=6176 ms
************ concatTest() ************
{str.concat("a")} cost=1267 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=3 ms
************ StringBuilderTest() ************
Disconnected from the target VM, address: '127.0.0.1:63841', transport: 'socket'
{strBuilder.append("a")} cost=2 ms
执行300000次时
************ plusTest() ************
{str + "a"} cost=23554 ms
************ concatTest() ************
{str.concat("a")} cost=17667 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=6 ms
************ StringBuilderTest() ************
{strBuilder.append("a")} cost=5 ms
执行500000次时
************ plusTest() ************
{str + "a"} cost=61421 ms
************ concatTest() ************
{str.concat("a")} cost=53173 ms
************ StringBufferTest() ************
{strBuffer.append("a")} cost=9 ms
************ StringBuilderTest() ************
{strBuilder.append("a")} cost=7 ms
1、 方法1 "+"号和方法2 contact()方法适用于数据量比较小的情况下。为了操作代码风格和养成习惯,还是建议尽量不用
2、方法2 StringBuffer 的 append()方法和StringBuilder 的 append()方法 本质上是一样的,均继承自AbstractStringBuilder抽象类,效率很高,数据量比较大的时候的推荐用法。区别是StringBuffer 是线程安全的,而StringBuilder是线程不安全的。
三、源代码分析
1、 String的"+"方法,编译器对其做了优化,使用StringBuilder的append()方法进行追加,但是每循环一次都会创建一个StringBuilder对象,且都会调用toString()方法转换为字符串,因此开销很大。
注:执行一次String的"+"方法,相当于str = new StringBuilder(str).append("x").toString();
2、调用String 的contact()方法,其实就是一次数组的拷贝,虽然在内存中的处理都是原子操作,速度很快,但是当返回时是要创建一个新的String对象的,这样不仅限制了效率,更添加了空间的压力,源码如下:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
3、StringBuffer和StringBuilder的append()方法均主要使用父类AbstractStringBuilder的append()方法。源码如下:
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;
}
即当数组空间够用的时候,只是在数组后面添加字符或字符串,并不创建新的对象,只是到最后通过toString()方法来生成最终的字符串,效率很快,也很节省空间,是推荐的用法。
参考
https://www.cnblogs.com/twzheng/p/5923642.html
Java 字符串拼接四种方式的性能比较分析的更多相关文章
- Java 字符串拼接 五种方法的性能比较分析 从执行100次到90万次
[请尊重原创版权,如需引用,请注明来源及地址] > 字符串拼接一般使用“+”,但是“+”不能满足大批量数据的处理,Java中有以下五种方法处理字符串拼接,各有优缺点,程序开发应选择合适的方法实现 ...
- Java 字符串拼接5种方式性能比较
https://www.cnblogs.com/twzheng/p/5923642.html
- Java基础知识强化25:Java创建对象的四种方式
1. Java程序中对象的创建有四种方式: ● 调用new语句创建对象,最常见的一种 ● 运用反射手段创建对象,调用java.lang.Class 或者 java.lang.reflect.Const ...
- PHP定义字符串的四种方式
1.简介 在PHP中这门语言中,因为是弱类型语言,因此使用变量时不需提前定义即可使用. 我们在使用php进行开发的时候,大多数使用双引号.单引号进行定义字符串.既然有这两种方式,那么他们之间肯定是有区 ...
- C# 拼接字符串的几种方式和性能
开发过程中常用到的拼接字符串的方法有三种: 1 简单 “+=” 拼接法 1 2 3 4 5 string str="a"; str+="c"+"d ...
- 使用位运算、值交换等方式反转java字符串-共四种方法
在本文中,我们将向您展示几种在Java中将String类型的字符串字母倒序的几种方法. StringBuilder(str).reverse() char[]循环与值交换 byte循环与值交换 apa ...
- java 多线程实现四种方式解析Thread,Runnable,Callable,ServiceExcutor,Synchronized ,ReentrantLock
1.Thread实现: import java.util.Date; import java.text.SimpleDateFormat; public class MyThread extends ...
- Java创建线程四种方式
1.继承Thread类 public class MyThread extends Thread { public MyThread() { } public void run() { for(int ...
- java创建对象的四种方式
1.最常见的 new 一个 2使用反射机制创建对象,直接调用非构造函数 Class obj=Class.forName("A"); A a=obj.newInstance(); C ...
随机推荐
- edgedb 内部pg 数据存储的探索 (一)基本环境搭建
edgedb 是基于pg 上的对象关系数据库,已经写过使用docker 运行的demo,为了探索内部的原理,做了一下尝试,开启pg 访问 后边会进一步的学习 环境准备 为了测试,使用yum 安装 安装 ...
- Eamon 埃蒙
发售年份 1980 平台 AppleII 开发商 Donald Brown 类型 文字冒险 https://www.youtube.com/watch?v=uvZIxnIvRG8
- vue- 项目之前端页面搭建1
项目分析 首页 导航.登录注册栏.轮播图.地板导航登录注册 选项卡免费课 课程分类.筛选.课程列表免费课详情 课程封面视频.优惠活动倒计时.选项卡我的购物车 全选.商品价格统计购买结算 购买成功 我的 ...
- update_engine-DownloadAction(二)
在update_engine-DownloadAction(一)中对DownloadAction介绍到了DeltaPerformer的Write方法.下面开始介绍Write方法. src/system ...
- sql调优2
今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数据 ...
- Android studio 中添加依赖model时依赖所需的准备
例如向app中添加依赖core: core要做如下修改: 1.将core中build.gradle中 修改为 . 2.将core中的 applicationId 注释掉.
- 工控随笔_18_西门子_WinCC的VBS脚本_07_变量作用域和传值、传址
在vbs脚本中也存在和其他编程语言一样的概念,那就是变量的作用域,变量的作用域决 定在什么范围内可以访问. 同样的在vbs脚本中对于变量也有一个生命周期, 变量的生命周期决定了变量的存续时间 这个主要 ...
- python基础知识14---迭代器、生成器、面向过程编程
阅读目录 一 迭代器 二 生成器 三 面向过程编程 一 迭代器 1 迭代的概念 #迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初 ...
- ScheduledThreadPoolExecutor线程池scheduleAtFixedRate和scheduleWithFixedDelay的区别
ScheduledFuture<?> result = executor.scheduleAtFixedRate(task,2, 5, TimeUnit.SECONDS); 在延迟2秒之后 ...
- [转][SerialPort]测试用例
private void Form1_Load(object sender, EventArgs e) { var s = SerialPort.GetPortNames().OrderBy(r =& ...