字符串拼接還在用StringBuilder?快試試Java8中的StringJoiner吧,真香!
前言
之前,我們經(jīng)常會通過StringBuffer或者StingBuilder對字符串進行拼接,但是你知道Java8中推出的StringJoiner嗎?它比前者更加優(yōu)美、靈活,如果你現(xiàn)在還使用StringBuffer拼接,強烈推薦你試試StringJoiner。
介紹
在實用StringJoiner類之前,如果我們想要數(shù)據(jù)最終的字符串以逗號隔開,大概是這樣的
- StringBuilder sb = new StringBuilder();
- IntStream.range(1,10).forEach(i->{
- sb.append(i+"");
- if( i < 10){
- sb.append(",")
- }
- });
如果引入StringJoiner,如何處理呢?
- StringJoiner sj = new StringJoiner(",");
- IntStream.range(1,10).forEach(i->sj.add(i+""));
看著是不是更簡單直觀了呢?
另外,StringJoiner類的構(gòu)造函數(shù),還可以做到可選擇性地從我們自定義的前綴開始和自定義的后綴結(jié)尾,比較靈活和實用。
- //值依次是分割符 , 前綴 ,后綴
- StringJoiner stringJoiner = new StringJoiner(",", "[", "]");
- stringJoiner.add("xiao");
- stringJoiner.add("zhi");
- System.out.println(stringJoiner.toString());
輸出結(jié)果:[xiao,zhi]
StringJoiner在處理sql拼接上面,也非常方便,如拼接 sql 的in條件的時候:
- StringJoiner joiner3 = new StringJoiner("','", "'", "'");
- joiner3.add("1").add("2");
- //輸出 : '1','2'
更多實用的功能,大家可以探索。
源碼
這個類的源碼很簡單,大家很容易就可以看明白。StringJoiner 更像一個裝飾者模式,對外隱藏了StringBuilder。
不過需要注意的是 StringJoiner 并且沒有處理一些基本的集合元素情況,比如加入列表的元素,更像針對Collectors而設(shè)計。
- 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, "", "");
- //默認前綴和后綴為"",重載調(diào)用
- }
- 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();
- thisthis.emptyValue = this.prefix + this.suffix;//空值被設(shè)置為只有前后綴
- }
- //設(shè)置空值,檢查是否為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;
- //沒有值將返回空值或者后續(xù)設(shè)置的空值
- } 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后續(xù)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());
- }
- }