Java中字符串常见的拼接方式
Posted Java小白笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中字符串常见的拼接方式相关的知识,希望对你有一定的参考价值。
文章目录
方式一:+ 最常见的方式
String aa = "今天";
String bb = "明天";
System.out.println(aa+bb);
方式二:StringBuilder.append()和StringBuffer.append()
先有StringBuffer后有StringBuilder,两者就像是孪生双胞胎,该有的都有,只不过大哥StringBuffer,大部分方法都经过synchronized修饰,所以StringBuffer是线程安全的,但是它效率就相对StringBuilder较低
String aa = "今天";
String bb = "明天";
StringBuilder sber = new StringBuilder();
StringBuffer sbf = new StringBuffer();
sber.append(aa).append(bb);
System.out.println(sber.toString());
sbf.append(aa).append(bb);
System.out.println(sbf.toString());
方式三:String类下的cocat()方法
如果拼接的字符串是null,concat会抛出NullPointerException。如果拼接的字符串是一个空字符串(“”),那么concat的效率要更高。如果拼接的字符串非常多,concat的效率就会下降,因为创建的字符串对象越多,开销越大。
String aa = "今天";
String bb = "明天";
String concat = aa.concat(bb);
System.out.println(concat);
方式四:String类下的join()方法
JDK1.8提供了一种新的字符串拼接姿势:String类增加了一个静态方法join,第一个参数为字符串连接符
String aa = "今天";
String bb = "明天";
String join = String.join("-", aa, bb);
System.out.println(join);
方式五:StringJoiner
StringJoiner是JDK1.8,java.util包中的一个类,用于构造一个由分隔符重新连接的字符序列
String aa = "今天";
String bb = "明天";
StringJoiner sj = new StringJoiner(":", "[", "]");
sj.add(aa).add(bb);
System.out.println(sj.toString());
StringJoiner源码
package java.util;
public final class StringJoiner
private final String prefix;//前缀
private final String delimiter;//间隔符
private final String suffix;//后缀
private StringBuilder value;//值
private String emptyValue;//空值
public StringJoiner(CharSequence delimiter)
this(delimiter, "", "");//默认前缀和后缀为"",重载调用
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix)
//间隔符,前缀和后缀判断是否为null,null将抛出异常
Objects.requireNonNull(prefix, "The prefix must not be null");
Objects.requireNonNull(delimiter, "The delimiter must not be null");
Objects.requireNonNull(suffix, "The suffix must not be null");
// 成员变量赋值
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
this.emptyValue = this.prefix + this.suffix;//空值被设置为只有前后缀
//设置空值,检查是否为null
public StringJoiner setEmptyValue(CharSequence emptyValue)
this.emptyValue = Objects.requireNonNull(emptyValue,
"The empty value must not be null").toString();
return this;
@Override
public String toString()
if (value == null)
return emptyValue;//没有值将返回空值或者后续设置的空值
else
if (suffix.equals(""))
return value.toString();//后缀为""直接返回字符串,不用添加
else
//后缀不为"",添加后缀,然后直接返回字符串,修改长度
int initialLength = value.length();
String result = value.append(suffix).toString();
// reset value to pre-append initialLength
value.setLength(initialLength);
return result;
初始化,先添加前缀,有了之后每次先添加间隔符,StringBuilder后续append字符串
public StringJoiner add(CharSequence newElement)
prepareBuilder().append(newElement);
return this;
//合并StringJoiner,注意后面StringJoiner 的前缀就不要了,后面的appen进来
public StringJoiner merge(StringJoiner other)
Objects.requireNonNull(other);
if (other.value != null)
final int length = other.value.length();
// lock the length so that we can seize the data to be appended
// before initiate copying to avoid interference, especially when
// merge 'this'
StringBuilder builder = prepareBuilder();
builder.append(other.value, other.prefix.length(), length);
return this;
//初始化,先添加前缀,有了之后每次先添加间隔符
private StringBuilder prepareBuilder()
if (value != null)
value.append(delimiter);
else
value = new StringBuilder().append(prefix);
return value;
public int length()
// Remember that we never actually append the suffix unless we return
// the full (present) value or some sub-string or length of it, so that
// we can add on more if we need to.
//不忘添加后缀的长度
return (value != null ? value.length() + suffix.length() :
emptyValue.length());
方式六:StringUtils.join()
实战项目中,我们处理字符串的时候,经常会用到这个类.org.apache.commons.lang3.StringUtils包下,该方法更善于拼接数组中的字符串,并且不用担心 NullPointerException。
String aa = "今天";
String bb = "明天";
String ids[] = "1","2","3";
System.out.println(StringUtils.join(aa,bb,"-","124"));
String join1 = StringUtils.join(ids,",");
System.out.println(join1);
Java 中拼接 String 的 N 种方式
文章持续更新,可以关注公众号程序猿阿朗或访问未读代码博客。
本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star。
1. 前言
Java 提供了拼接 String 字符串的多种方式,不过有时候如果我们不注意 null
字符串的话,可能会把 null
拼接到结果当中,很明显这不是我们想要的。
在这篇文章中,将介绍一些在拼接 String 时避免 null
值的几种方式。
2. 问题复现
如果我们想要拼接 String 数组,可以简单的使用 +
运算符进行拼接,但是可能会遇到 null
值。
String[] values = "https", "://", "www.", "wdbyte", ".com", null;
String result = "";
for (String value : values)
result = result + value;
这会将所有元素拼接到结果字符串中,如下所示:
https://www.wdbyte.comnull
但是,我们已经发现问题了,最后的 null
值作为字符串也拼接了下来,这显然不是我们想要的。
同样,即使我们在 Java 8 或更高版本上运行,然后使用String.join() 静态方法拼接字符串,一样会得到带有 null
值的输出。
String[] values = "https", "://", "www.", "wdbyte", ".com", null;
String result = String.join("", values);
// output: https://www.wdbyte.comnull
下面看看一些可以避免 null
值被拼接下来的方法,我的期待的输出结果应该是:
https://www.wdbyte.com
3. 使用 + 运算符
加法符号 +
可以拼接 String 字符串,那么我们只需要在拼接时进行 null
判断就可以把 null
值替换为空字符串了。
for (String value : values)
result = result + (value == null ? "" : value);
然而,我们知道 String 是一个不可变对象,使用 +
号会频繁的创建字符串对象,每次都会在内存中创建一个新的字符串,所以使用 +
符号来拼接字符串的性能消耗是很高的。
为了方便后续的代码演示,我们抽取一个可以传入字符串,返回一个非 null 字符串的方法。
public String nullToString(String value)
return value == null ? "" : value;
因此上面的代码可以改为调用这个方法:
for (String value : values)
result = result + nullToString(value);
4. 使用 String.concat()
String.concat()
是 String 类自带的一个方法,使用这种方式拼接字符串十分方便。
for (String value : values)
result = result.concat(getNonNullString(value));
因为调用了 nullToString()
方法,因此得到的结果中没有 null
值。
5. 使用 StringBuilder
StringBuilder 类提供了很多有用且方便的 String 构建方法。其中比较常用的是 append()
方法,使用 append()
来拼接字符串,同时结合 nullToString()
方法来避免 null
值。
String[] values = "https", "://", "www.", "wdbyte", ".com", null;
StringBuilder result = new StringBuilder();
for (String value : values)
result = result.append(nullToString(value));
可以得到如下结果:
https://www.wdbyte.com
6. 使用 StringJoiner 类 (Java 8+)
StringJoiner 类提供了更强大的字符串拼接功能,不仅可以指定拼接时的分隔符,还可以指定拼接时的前缀和后缀,这里我们可以使用它的 add()
方法来拼接字符串。
同样的会用 nullToString()
方法来避免 null
值。
String[] values = "https", "://", "www.", "wdbyte", ".com", null;
StringJoiner result = new StringJoiner("");
for (String value : values)
result = result.add(nullToString(value));
7. 使用 Streams.filter (Java 8+)
Stream API 是 Java 8 引入的功能强大的流式操作类,可以进行常见的过滤、映射、遍历、分组、统计等操作。其中的过滤操作 filter
可以接收一个 Predicate 函数,Predicate 函数接口同之前介绍的 Function (opens new window)接口一样,是一个函数式接口,它可以接受一个泛型 <T>
参数,返回值为布尔类型,Predicate 常用于数据过滤。
因此,我们可以定义一个Predicate 来检查为 null
的字符串,然后传递给 Stream API 的 filter()
方法。
最后再使用 Collectors.joining()
方法拼接剩余的非 null
字符串。
String[] values = "https", "://", "www.", "wdbyte", ".com", null;
String result = Arrays.stream(values)
.filter(Objects::nonNull)
.collect(Collectors.joining());
8. 总结
这篇文章介绍了拼接非 null
字符串的几种方式,不同的方式可能适合不同的场景,不过要注意拼接String 字符串是一项昂贵的操作,下面是使用 JMH 对几种拼接方式进行基准测试的结果。
Benchmark Mode Cnt Score Error Units
StringConcat.operateAdd thrpt 25 13635005.992 ± 549759.774 ops/s
StringConcat.String.concat thrpt 25 7465193.417 ± 667928.552 ops/s
StringConcat.StringBuilder thrpt 25 13949781.608 ± 142001.421 ops/s
StringConcat.StringJoiner thrpt 25 9502405.473 ± 211977.433 ops/s
StringConcat.StreamFilter thrpt 25 8998396.107 ± 649033.722 ops/s
可以看到 StringBuilder 的性能是最好的,实际使用时要结合具体场景,然后选择最低的性能开销方式。
一如既往,文章中的代码存放在:github.com/niumoo/JavaNotes
订阅
可以微信搜一搜程序猿阿朗或访问未读代码博客阅读。
本文 Github.com/niumoo/JavaNotes 已经收录,欢迎Star。
以上是关于Java中字符串常见的拼接方式的主要内容,如果未能解决你的问题,请参考以下文章