我已阅读有关 StringBuilder API、StringJoiner API 和 String.join 的信息,但不确定 StringBuilder 实例中是否有项目,可以使用哪个调用来使用所选分隔符进行连接。我不想手动迭代并执行此操作(在某种程度上容易出错)
以下返回没有分隔符的结果:
StringBuilder sb = new StringBuilder();
sb.append("s1");
sb.append("s2");
String str2 = String.join("::",sb);
System.out.println(str2);
上面的输出为s1s2
。但我不确定为什么?
1
最佳答案
4
这是不可能的。StringBuilder 不会维护稍后可以连接的单独元素。当您尝试调用时,元素边界已经丢失String.join
。
您需要从一开始就使用 StringJoiner,或者如果您由于某种原因确实被迫使用 StringBuilder,则需要手动在项目之间添加分隔符。
|
总结
您预料到了结果吗s1::s2
?
然后,您需要研究文档以了解那StringBuilder
是一段文本,而不是多段文本的集合。
尝试:
String.join( "::" , List.of( "s1" , "s2" ) )
s1::s2
细节
您误解了StringBuilder
类和String.join
方法。
StringBuilder
该类并不代表文本部分的集合。
StringBuilder
表示一段文本。每次调用 时,当前内容都会与传递的文本组合起来,形成一段新文本,成为新内容。附加部分没有历史记录;一个StringBuilder
对象只有一段文本。
String.join
该String.join
方法用于接收多段文本。第一个参数是要连接的各个文本段之间使用的分隔符。在第一个参数之后,您应该:
- 传递多段文本(而不只是一段),或者
- 传递一个
Iterable< ? extends CharSequence >
诸如 aaList
的String
对象。
因此,如果我们传递两段文本,例如“dog”和“cat”,并以“::”作为分隔符,我们就会得到dog::cat
。
String result = String.join( "::" , "dog" , "cat" ) ;
狗::猫
合并一段文本毫无意义
但是您只传递了两个参数,即分隔符和一段文本。如果只有一段文本,分隔符就毫无用处。
String result = String.join( "::" , "dog" ) ;
狗
因此,编写像该示例这样的代码真的毫无意义,只有“狗”而没有其他文本。
您的代码:
String str2 = String.join("::",sb);
… 使用String.join
方法,您可以传递实现接口的任何类型的对象CharSequence
。String
&都StringBuilder
实现CharSequence
。因此,传递StringBuilder
参数是合法的,就像我们上面的例子传递“狗”是合法的一样。
但是就像我们上面的例子一样,只传递“dog”,这里的代码确实没有意义。你原来的文本片段“s1”和“s2”已经在你的StringBuilder
对象中组合了。所以你只传递“sb”的结果和你写的结果是一样的:
String str2 = String.join("::","s1s2");
结果是四个字符的字符串:
s1s2
显然,您期望的结果为s1::s2
。但您的期望是不正确的。
一如既往,根据文档编程比根据直觉编程更好。引用 Javadoc 的第一句话StringBuilder
:
可变的字符序列。
该文档并未提及它是多段文本的集合。
连接文本片段集合
如果您想要多个文本的集合,请使用类似或 的实现。从技术上讲,您需要一个Iterable< ? extends CharSequence >
。
SequencedCollection < String > piecesOfText = new ArrayList <>( );
piecesOfText.add( "s1" );
piecesOfText.add( "s2" );
String result = String.join( "::" , piecesOfText );
System.out.println( result );
s1::s2
或者更简洁地说:
String result = String.join( "::" , List.of( "s1" , "s2" ) );
System.out.println( result );
结果相同。
s1::s2
|
您也可以使用流来实现。我提到这一点的原因是它提供了包含前缀和后缀的选项。
以下是一些示例。
这就是您要做的事情。
String str3 = Stream.of("s1","s2").collect(Collectors.joining("::"));
System.out.println(str3);
印刷
s1::s2
这里提供了前缀/后缀字符串。
String str3 = Stream.of("s1","s2").collect(Collectors.joining("::", "[", "]"));
System.out.println(str3);
印刷
[s1::s2]
您还可以使用数组和列表。这是一个数组示例。对于 a,list
它只是list.stream()...
“;
String[] strs = {"s1", "s2"};
String str3 = Arrays.stream(strs).collect(Collectors.joining("::", "[", "]"));
System.out.println(str3);
印刷
[s1::s2]
|
您遇到的问题是由于对StringBuilder
和如何String.join()
协同工作的误解。StringBuilder
该类不跟踪单个元素;它只是附加字符以创建单个连续序列。当您调用 时sb.append("s1"); sb.append("s2");
,StringBuilder
包含“s1s2”作为一个字符串,而不是单独的元素。
当您将 传递sb
给 时String.join("::", sb);
,它不会使用分隔符“::”连接多个字符串,因为StringBuilder
不是数组或字符串集合。相反,它被视为单个CharSequence
,因此不会发生连接,也不会插入分隔符。
为了实现“s1::s2”的期望输出,请考虑以下替代方法:
1. 使用List
来收集字符串,然后将它们连接起来:
List<String> items = new ArrayList<>();
items.add("s1");
items.add("s2");
String result = String.join("::", items);
System.out.println(result); // Outputs: s1::s2
2.使用方法StringJoiner
:
StringJoiner sj = new StringJoiner("::");
sj.add("s1");
sj.add("s2");
String result = sj.toString();
System.out.println(result); // Outputs: s1::s2
3. 使用以下方式手动添加分隔符StringBuilder
:
StringBuilder sb = new StringBuilder();
sb.append("s1").append("::").append("s2");
String result = sb.toString();
System.out.println(result); // Outputs: s1::s2
解释:
- 选项 1:收集中的字符串
List
允许您有效地使用String.join()
,因为它可以遍历集合并在元素之间插入分隔符。 - 选项 2:
StringJoiner
专门用于连接带有分隔符的字符串,而无需手动管理分隔符。 - 选项 3:如果您更喜欢使用
StringBuilder
,则需要在字符串之间自行添加分隔符,因为StringBuilder
它不会自动处理分隔符。
为什么你的原始代码不起作用:
您的原始代码未插入分隔符,因为String.join("::", sb);
使用不正确。String.join()
需要一个分隔符和一个数组或一个Iterable
实例CharSequence
(如一个List
对象String
)。由于StringBuilder
未实现Iterable<CharSequence>
,并且它表示单个字符序列,该方法没有多个元素要连接,因此不应用分隔符。
正确用法String.join()
:
如果您有一个数组或字符串集合,您可以String.join()
像这样使用:
String[] strings = {"s1", "s2"};
String result = String.join("::", strings);
System.out.println(result); // Outputs: s1::s2
结论:
要在字符串之间插入分隔符,您需要使用包含单个元素的数据结构,例如List
或 数组,然后使用String.join()
或StringJoiner
。如果您使用StringBuilder
,则必须在字符串之间手动添加分隔符。
|
join
是参数,因此您只提供了一个要连接的字符串。例如,String.join("::","s1","s2")
将生成s1::s2
。看来您的StringBuilder
方法无法实现这一点。–
|