diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb291f8a1..d8d57d7c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
# 🚀Changelog
-------------------------------------------------------------------------------------------------------------
-# 5.7.22 (2022-02-26)
+# 5.7.22 (2022-02-27)
### 🐣新特性
* 【poi 】 ExcelUtil.readBySax增加对POI-5.2.0的兼容性(issue#I4TJF4@gitee)
@@ -16,6 +16,8 @@
* 【http 】 增加HttpGlobalConfig.setDecodeUrl(issue#I4U8YQ@Gitee)
* 【core 】 增加Base58(pr#2162@Github)
* 【core 】 增加AntPathMatcher(issue#I4T7K5@Gitee)
+* 【core 】 StrJoiner修改toString策略,调用不再修改Appendable
+* 【core 】 StrJoiner增加length和merge方法
### 🐞Bug修复
* 【cache 】 修复ReentrantCache.toString方法线程不安全问题(issue#2140@Github)
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java
index e41e9b84f..5d9c9d87a 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/CollectorUtil.java
@@ -14,7 +14,6 @@ import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
import java.util.stream.Collector;
import java.util.stream.Collectors;
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java b/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java
index bfebd8703..e2a8a5387 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/StrJoiner.java
@@ -12,7 +12,14 @@ import java.util.Iterator;
import java.util.function.Function;
/**
- * 字符串连接器(拼接器),通过给定的字符串和多个元素,拼接为一个字符串
+ * 字符串连接器(拼接器),通过给定的字符串和多个元素,拼接为一个字符串
+ * 相较于{@link java.util.StringJoiner}提供更加灵活的配置,包括:
+ *
+ * - 支持任意Appendable接口实现
+ * - 支持每个元素单独wrap
+ * - 支持自定义null的处理逻辑
+ * - 支持自定义默认结果
+ *
*
* @author looly
* @since 5.7.2
@@ -282,6 +289,11 @@ public class StrJoiner implements Appendable, Serializable {
@Override
public StrJoiner append(CharSequence csq) {
+ return append(csq, 0, csq.length());
+ }
+
+ @Override
+ public StrJoiner append(CharSequence csq, int startInclude, int endExclude) {
if (null == csq) {
switch (this.nullMode) {
case IGNORE:
@@ -298,7 +310,7 @@ public class StrJoiner implements Appendable, Serializable {
if (wrapElement && StrUtil.isNotEmpty(this.prefix)) {
appendable.append(prefix);
}
- appendable.append(csq);
+ appendable.append(csq, startInclude, endExclude);
if (wrapElement && StrUtil.isNotEmpty(this.suffix)) {
appendable.append(suffix);
}
@@ -308,29 +320,55 @@ public class StrJoiner implements Appendable, Serializable {
return this;
}
- @Override
- public StrJoiner append(CharSequence csq, int startInclude, int endExclude) {
- return append(StrUtil.sub(csq, startInclude, endExclude));
- }
-
@Override
public StrJoiner append(char c) {
return append(String.valueOf(c));
}
+ /**
+ * 合并一个StrJoiner 到当前的StrJoiner
+ * 合并规则为,在尾部直接追加,当存在{@link #prefix}时,如果{@link #wrapElement}为{@code false},则去除之。
+ *
+ * @param strJoiner 其他的StrJoiner
+ * @return this
+ * @since 5.7.22
+ */
+ public StrJoiner merge(StrJoiner strJoiner){
+ if(null != strJoiner && null != strJoiner.appendable){
+ final String otherStr = strJoiner.toString();
+ if(strJoiner.wrapElement){
+ this.append(otherStr);
+ }else{
+ this.append(otherStr, this.prefix.length(), otherStr.length());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * 长度
+ * 长度计算方式为prefix + suffix + content
+ * 此方法结果与toString().length()一致。
+ *
+ * @return 长度,如果结果为{@code null},返回-1
+ * @since 5.7.22
+ */
+ public int length() {
+ return (this.appendable != null ? this.appendable.toString().length() + suffix.length() :
+ null == this.emptyResult ? -1 : emptyResult.length());
+ }
+
@Override
public String toString() {
if (null == this.appendable) {
return emptyResult;
}
+
+ String result = this.appendable.toString();
if (false == wrapElement && StrUtil.isNotEmpty(this.suffix)) {
- try {
- this.appendable.append(this.suffix);
- } catch (IOException e) {
- throw new IORuntimeException(e);
- }
+ result += this.suffix;
}
- return this.appendable.toString();
+ return result;
}
/**
diff --git a/hutool-core/src/test/java/cn/hutool/core/text/StrJoinerTest.java b/hutool-core/src/test/java/cn/hutool/core/text/StrJoinerTest.java
index 2ce2eee8c..f9a2d4c30 100644
--- a/hutool-core/src/test/java/cn/hutool/core/text/StrJoinerTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/text/StrJoinerTest.java
@@ -78,4 +78,25 @@ public class StrJoinerTest {
.append("3");
Assert.assertEquals("[1],[2],[3]", append.toString());
}
+
+ @Test
+ public void lengthTest(){
+ StrJoiner joiner = StrJoiner.of(",", "[", "]");
+ Assert.assertEquals(joiner.toString().length(), joiner.length());
+
+ joiner.append("123");
+ Assert.assertEquals(joiner.toString().length(), joiner.length());
+ }
+
+ @Test
+ public void mergeTest(){
+ StrJoiner joiner1 = StrJoiner.of(",", "[", "]");
+ joiner1.append("123");
+ StrJoiner joiner2 = StrJoiner.of(",", "[", "]");
+ joiner1.append("456");
+ joiner1.append("789");
+
+ final StrJoiner merge = joiner1.merge(joiner2);
+ Assert.assertEquals("[123,456,789]", merge.toString());
+ }
}