我已阅读有关 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

  • 3
    请注意,的第二个以上参数join参数,因此您只提供了一个要连接的字符串。例如,String.join("::","s1","s2")将生成s1::s2。看来您的StringBuilder方法无法实现这一点。


    – 



最佳答案
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 >诸如 aaListString对象。

因此,如果我们传递两段文本,例如“dog”和“cat”,并以“::”作为分隔符,我们就会得到dog::cat

String result = String.join( "::" , "dog" , "cat" ) ;

狗::猫

合并一段文本毫无意义

但是您只传递了两个参数,即分隔符和一段文本。如果只有一段文本,分隔符就毫无用处。

String result = String.join( "::" , "dog" ) ;

因此,编写像该示例这样的代码真的毫无意义,只有“狗”而没有其他文本。

您的代码:

String str2 = String.join("::",sb);

… 使用String.join方法,您可以传递实现接口的任何类型的对象CharSequenceString&都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,则必须在字符串之间手动添加分隔符。