平时我们进行字符串拼接时,最常用的就是StringBuilder和StringBuffer了,但是在JDK 1.8+中,引入了一个字符串拼接神器:StringJoiner。
例如:
hello,world,欢迎使用StringJoiner
在JDK 1.8之前,需要使用StringBuilder或者StringBuffer来进行拼接。
StringBuilder stb = new StringBuilder();
stb.append("hello");
stb.append(",");
stb.append("world");
stb.append(",");
stb.append("欢迎使用StringJoiner");
System.out.println(stb);
其中包含了许多分隔符,如果拼接的字符串非常多,代码就会显得非常臃肿。但是在JDK 1.8+有了StringJoiner,这件事就变得很简单了,分隔符全部都交给了StringJoiner处理
StringJoiner stj = new StringJoiner(",");
stj.add("hello");
stj.add("world");
stj.add("欢迎使用StringJoiner");
System.out.println(stj);
从类结构图中可以看出,StringJoiner的属性有:
prefix:拼接后的字符串前缀
delimiter:拼接时的字符串分隔符
suffix:拼接后的字符串后缀
value:拼接后的值
emptyValue:空值的情况,value为null时返回
setEmptyValue():设置空值
toString():转换成String
add():添加字符串
merge():从另一个StringJoiner合并
length():长度(包括前后缀)
/**
* Constructs a {@code StringJoiner} with no characters in it, with no
* {@code prefix} or {@code suffix}, and a copy of the supplied
* {@code delimiter}.
* If no characters are added to the {@code StringJoiner} and methods
* accessing the value of it are invoked, it will not return a
* {@code prefix} or {@code suffix} (or properties thereof) in the result,
* unless {@code setEmptyValue} has first been called.
*
* @param delimiter the sequence of characters to be used between each
* element added to the {@code StringJoiner} value
* @throws NullPointerException if {@code delimiter} is {@code null}
*/
public StringJoiner(CharSequence delimiter) {
this(delimiter, "", "");
}
/**
* Constructs a {@code StringJoiner} with no characters in it using copies
* of the supplied {@code prefix}, {@code delimiter} and {@code suffix}.
* If no characters are added to the {@code StringJoiner} and methods
* accessing the string value of it are invoked, it will return the
* {@code prefix + suffix} (or properties thereof) in the result, unless
* {@code setEmptyValue} has first been called.
*
* @param delimiter the sequence of characters to be used between each
* element added to the {@code StringJoiner}
* @param prefix the sequence of characters to be used at the beginning
* @param suffix the sequence of characters to be used at the end
* @throws NullPointerException if {@code prefix}, {@code delimiter}, or
* {@code suffix} is {@code null}
*/
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
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");
// make defensive copies of arguments
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
}
StringJoiner提供了两个构造器,一个必须带分隔符,另一个必须带分隔符、前缀、后缀。
public class Test {
public static void main(String[] args) {
StringJoiner stj = new StringJoiner(",", "--", "++");
stj.add("hello");
stj.add("world");
stj.add("欢迎使用StringJoiner");
System.out.println(stj);
}
}
--hello,world,欢迎使用StringJoiner++
public class Test {
public static void main(String[] args) {
StringJoiner stj = new StringJoiner(",");
System.out.println(stj.toString());
}
}
输出空白字符串
public class Test {
public static void main(String[] args) {
StringJoiner stj = new StringJoiner(",", "[", "]");
System.out.println(stj.toString());
}
}
[]
public class Test {
public static void main(String[] args) {
StringJoiner stj = new StringJoiner(",", "[", "]");
stj.setEmptyValue("empty");
System.out.println(stj.toString());
}
}
empty
String.join()是对StringJoiner的又一层封装API,也是出自JDK 1.8+,可以传入动态的参数或者迭代器。
源码:
/**
* Returns a new String composed of copies of the
* {@code CharSequence elements} joined together with a copy of
* the specified {@code delimiter}.
*
* For example,
* {@code
* String message = String.join("-", "Java", "is", "cool");
* // message returned is: "Java-is-cool"
* }
*
* Note that if an element is null, then {@code "null"} is added.
*
* @param delimiter the delimiter that separates each element
* @param elements the elements to join together.
*
* @return a new {@code String} that is composed of the {@code elements}
* separated by the {@code delimiter}
*
* @throws NullPointerException If {@code delimiter} or {@code elements}
* is {@code null}
*
* @see java.util.StringJoiner
* @since 1.8
*/
public static String join(CharSequence delimiter, CharSequence... elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
// Number of elements not likely worth Arrays.stream overhead.
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
/**
* Returns a new {@code String} composed of copies of the
* {@code CharSequence elements} joined together with a copy of the
* specified {@code delimiter}.
*
* For example,
* {@code
* List strings = List.of("Java", "is", "cool");
* String message = String.join(" ", strings);
* //message returned is: "Java is cool"
*
* Set strings =
* new LinkedHashSet<>(List.of("Java", "is", "very", "cool"));
* String message = String.join("-", strings);
* //message returned is: "Java-is-very-cool"
* }
*
* Note that if an individual element is {@code null}, then {@code "null"} is added.
*
* @param delimiter a sequence of characters that is used to separate each
* of the {@code elements} in the resulting {@code String}
* @param elements an {@code Iterable} that will have its {@code elements}
* joined together.
*
* @return a new {@code String} that is composed from the {@code elements}
* argument
*
* @throws NullPointerException If {@code delimiter} or {@code elements}
* is {@code null}
*
* @see #join(CharSequence,CharSequence...)
* @see java.util.StringJoiner
* @since 1.8
*/
public static String join(CharSequence delimiter,
Iterable extends CharSequence> elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
StringJoiner joiner = new StringJoiner(delimiter);
for (CharSequence cs: elements) {
joiner.add(cs);
}
return joiner.toString();
}
通过源码可以看出,这两个方法只能进行简单的拼接操作,不能添加前后缀、空值设置处理等。
微信公众号:macrozheng:《你只会StringBuilder?试试StringJoiner,真香!》