# 关于Java里面的字符串拼接,你了解多少?
### 前言
字符串拼接是我们日常开发中很常见的操作,虽然常见,但要是使用不当的的话,很有可能让你的程序处理效率降低一大半,所以我们有必要来重新了解一下Java里面的字符串操作。
### 基础知识回顾
(1)关于字符串字面量
```
String text="我是攻城师1";
```
上面的这行代码是我们最常见的声明方式,它会创建一个对象,并放在字符串常量池里面,关于常量池的内容,可以参考我之前的文章。
(2)关于new String
```
String text2=new String("我是攻城师2")
```
上面的这段代码是通过new的方式来创建字符串对象的,这里总共会产生2个对象,第一个是new创建的在堆内存里,第二个是字面量创建的在常量池里面。此外text2变量是在线程的栈里面,它只引用了堆里面的对象实例,这一点需要注意很多新手分不清楚他们之间的联系。
(3)关于String不可变性
Java的里面String类的有关操作,都会生成新的String实例,所以在大量修改操作时,应该使用可变的StringBuffer或者StringBuilder。
### 字符串拼接的几种方法
(1)使用 + 号
(2)使用字符串的concat方法
(3)StringBuffer的append方法
(4)StringBuilder的append方法
上面的四种就是Java里面所有的关于字符串拼接的方法,问题来了四种方法之间有什么区别?
* StringBuffer是线程安全的,StringBuilder是线程不安全的,大部分时候应该首选StringBuilder方法,它的字符串拼接效率最高,因为不会创建很多的String实例。
* +号与concat方法的:
首先+号是可以和各种类型拼接字符串的,而concat的参数必须是字符串类型,其次concat方法拼接null值是会抛空指针的,代码如下:
```
//DIFFERENCE 1
String a = null;
String b = "foo";
String c = a + b; // c = nullfoo
String d = b.concat(a); // 空指针
String e = a.concat(b); // 空指针
//DIFFERENCE 2
String x = "1" + 2; // x = 12
String y = "1".concat(2); // 编译错误
```
最后,他们在底层处理机制上也不同:
```
String c ="a" + "b";
```
上面的语句在编译的时候会转化成下面的代码:
```
c = new StringBuilder()
.append("a")
.append("b")
.toString();
```
注意上面的代码会涉及三次的new char[]数组分配和数组拷贝动作。
而同样的操作使用concat方法,则只会涉及一次的数组分组和数组拷贝:
```
String c=”a“.concat("b")
```
源码如下:
```
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);
}
```
### 字符串拼接的性能对比
下面我们分别对上面的四种方法在jdk8的mac系统上,进行1万次的拼接动作,看下性能表现,测试代码如下:
```
final int loop_count=10000;
// 1 +
String s1="s1";
long startTime=System.nanoTime();
for (int i = 0; i < loop_count; i++) {
s1=s1+Integer.toString(i);
}
long duration=System.nanoTime()-startTime;
System.out.println(" + cost: "+duration/1000+" 微秒 ");
// 2 concat
String s2="s2";
startTime=System.nanoTime();
for (int i = 0; i < loop_count; i++) {
s2=s2.concat(Integer.toString(i));
}
duration=System.nanoTime()-startTime;
System.out.println(" concat cost: "+duration/1000+" 微秒 ");
// 3 stringbuffer
StringBuffer s3=new StringBuffer("s3");
startTime=System.nanoTime();
for (int i = 0; i < loop_count; i++) {
s3.append(Integer.toString(i));
}
duration=System.nanoTime()-startTime;
System.out.println(" StringBuffer cost: "+duration/1000+" 微秒 ");
// 4 stringbuilder
StringBuilder s4=new StringBuilder("s4");
startTime=System.nanoTime();
for (int i = 0; i < loop_count; i++) {
s4.append(Integer.toString(i));
}
duration=System.nanoTime()-startTime;
System.out.println(" StringBuilder cost: "+duration/1000+" 微秒 ");
```
结果输出如下:
```
+ cost: 432673 微秒
concat cost: 49118 微秒
StringBuffer cost: 1011 微秒
StringBuilder cost: 734 微秒
```
从上面的循环1万次拼接的结果来看+操作符在循环loop中拼接字符串最耗时,前两个结果与后两个结果完全不在一个量级上,因为前面的两种方法在每次循环时候都会生成一个新的String实例返回,而后面的两个则只需要最后使用一次,至于StringBuffer比StringBuilder耗时是因为前者是同步的方法,后者则不是。
### 总结
(1)在没有线程问题的情况下大量修改字符串优先考虑StringBuilder
(2)在有线程问题的情况下大量修改字符串优先考虑StringBuffer
(3)如果仅仅是两个字符串的拼接优先考虑String类的concat方法
(4)如果一次性拼接多个字符串,可以考虑使用非循环模式下的+号拼接
或者直接使用StringBuilder对象。
(5)最后还有一个不常用的方法String.join其内部用的是StringBuilder类,所以不再多说。
分享到:
相关推荐
总结来说,Java中根据HTML模板生成新的HTML涉及到对HTML模板的理解,选择合适的处理方式(如字符串拼接或使用模板引擎),以及熟悉相关的Java库和API。通过这样的方法,我们可以快速地生成动态的、个性化的HTML页面...
1. **字符串基本操作**:包括创建、赋值、长度计算、字符串拼接、比较等。 2. **字符串分割**:使用`split()`函数,可以按照指定的分隔符将字符串切割成多个子串,如Python中的用法。 3. **正则表达式分隔**:通过...
- `j + "*" + i + "=" + j * i`:拼接字符串,形成如“1*2=2”的格式。 - `\t`:表示一个制表符,用于对齐输出。 - `System.out.println()`: - 每次内层循环结束后执行该语句,用于换行,使输出结果呈现为标准的...
例如,在文件`XiTi1_1_1.java`中,通过双重嵌套的`for`循环实现了从1到9的乘法表打印,其中外层循环控制行数,内层循环控制列数,通过字符串拼接和条件判断来格式化输出结果。 ### 数组的定义与操作 数组是存储同...
6. **字符串处理**:String类是Java中常用的一个类,源码中可能包含字符串的拼接、查找、替换等操作。 7. **函数式编程**:Java 8引入了Lambda表达式,使得函数式编程成为可能,源码中可能会有这方面的示例。 8. *...
例如,"StringUtil.java"可能包含各种字符串操作的方法,如字符串拼接、格式化、分割等;"DateUtil.java"则可能提供了日期和时间的转换、计算等功能。 在深入分析之前,我们需要了解源码的基本结构和命名规范。通常...
Java 判断数组中的数值是否连续相邻的方法 在 Java 编程语言中,判断一个数组中的数值是否连续相邻是一个常见的问题。今天,我们将分享一种简洁的方法来解决这个问题。 方法原理 该方法的主要思想是,遍历数组,...
3. **文本块(Text Blocks)**: 提供多行字符串字面量,避免了转义字符和拼接字符串的繁琐。 4. **HTTP客户端API**: 内置的HTTP客户端库,简化网络通信。 5. **静态工厂方法代替构造函数**: 对于`Optional`、`...
字符串问题在 LeetCode 中非常常见,涉及子串查找、拼接、替换等多种操作。 7. **递归与回溯**:这两种方法常用于解决复杂的问题,如搜索所有可能的解决方案或遍历树结构。理解和掌握递归原理至关重要。 8. **并发...
有一种特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子: ${r"/${data}"year""}屏幕输出结果为:/${data}"year" 转义 含义 ...
Ibatis 是MyBatis的前身,它提供了一个SQL映射框架,可以将SQL语句编写在XML配置文件中,避免在Java代码中直接拼接SQL字符串,降低了SQL注入的风险。Ibatis的核心是SqlSession接口,它负责执行SQL、处理结果集以及...
2. **条件构造器**:提供了一个强大的查询构造器,允许开发人员通过简单的API调用来构建复杂的SQL语句,避免了大量的字符串拼接,提高了代码的可读性和可维护性。 3. **动态SQL**:类似于MyBatis的动态XML标签,...
- 使用StringBuilder而非String进行字符串拼接,避免创建过多中间对象。 - 使用适当的数据结构和算法,遵循“早退原则”(尽早返回结果,避免不必要的计算)。 Codeforces-master这个文件名可能是该项目的源码...
3. **字符串处理**:Java的String类提供了丰富的字符串操作方法,如拼接、查找子串、替换、分割等。在Coding.Bat上,你将有机会实践这些操作。 4. **条件判断与逻辑运算**:包括if-else语句、switch语句以及逻辑...
5. **字符串处理**:字符串操作在编程中非常常见,LeetCode的题目可能涉及到字符串拼接、模式匹配、子串查找、字符计数等。 6. **数学应用**:一些题目需要运用到基础数学知识,比如组合数学、概率论、数论等。 7....
3. **字符串处理**:字符串的拼接、分割、查找子串、模式匹配等。 4. **递归**:在解决一些复杂问题时,如斐波那契数列、树的遍历等,递归是常用的方法。 5. **排序和搜索算法**:快速排序、归并排序、二分查找等...
2. **字符串操作**:Python的字符串是不可变的,但提供了丰富的操作方法,如切片、拼接、查找、替换、分割等。 3. **列表和元组**:列表是可变的有序集合,元组则是不可变的有序集合。它们都可以通过索引访问,支持...
2. **基本数据类型与结构**:讲解MATLAB中的基本数据类型,如标量、向量、矩阵和数组,以及复数、逻辑值和字符串。还会涉及结构体和细胞数组,这些复杂数据类型用于存储不同类型的数据。 3. **运算符与表达式**:...
1. **基础语法**:包括变量声明(var、let、const)、数据类型(字符串、数字、布尔值、对象、数组等)、条件语句(if...else、switch)、循环(for、while、do...while)等。 2. **函数**:函数的定义、参数传递、...
2. **语法与数据类型**:MATLAB支持多种数据类型,包括标量、向量、矩阵、数组、字符串等。理解这些数据类型的创建、操作和转换是学习MATLAB的基础。 3. **函数与脚本**:MATLAB允许用户定义自己的函数,通常以.m...