删除 StringBuilder 的最后一个字符?
当您必须循环遍历集合并使用分隔符分隔每个数据的字符串时,最后总会有一个额外的分隔符,例如
for (String serverId : serverIds) {
sb.append(serverId);
sb.append(",");
}
给出类似:serverId_1, serverId_2, serverId_3,
我想删除 StringBuilder 中的最后一个字符(不转换它,因为在这个循环之后我仍然需要它)。
When you have to loop through a collection and make a string of each data separated by a delimiter, you always end up with an extra delimiter at the end, e.g.
for (String serverId : serverIds) {
sb.append(serverId);
sb.append(",");
}
Gives something like : serverId_1, serverId_2, serverId_3,
I would like to delete the last character in the StringBuilder (without converting it because I still need it after this loop).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
在这种情况下,
更可取,因为它只是将最后一个值分配给
'\0'
而删除最后一个字符则执行System.arraycopy
In this case,
is preferable as it just assign the last value to
'\0'
whereas deleting last character doesSystem.arraycopy
使用
Java-8
,您可以使用String
类的静态方法,String#join(CharSequence delimiter,Iterable elements)
.输出
With
Java-8
you can use static method ofString
class,String#join(CharSequence delimiter,Iterable<? extends CharSequence> elements)
.OUTPUT
另一种选择
Another alternative
或者,
Alternatively,
还有另一种选择:
Yet another alternative:
为了避免
prefix
的重新初始化(影响性能),请使用 TextUtils.isEmpty:To avoid reinit(affect performance) of
prefix
use TextUtils.isEmpty:您可以尝试使用“Joiner”类,而不是从生成的文本中删除最后一个字符;
You may try to use 'Joiner' class instead of removing the last character from your generated text;
我正在做如下的事情:
I am doing something like below:
我发现自己经常这样做,所以我为 3 个主要附加分隔符技术编写了一个基准:
(经过适当热身和 100 轮 100,000 次迭代的基准)
“追加之后”
“追加之前”
“追加可能”
我得到以下结果:
除了最快之外,我认为“Append Maybe”实现最好地展示了代码的意图。这通常比每次迭代获得的纳秒分数更重要。
我将基准代码留在这里,以防有人想在他们的平台上尝试。如果您这样做,请在上面贡献您的结果!
I found myself doing this quite a bit so I wrote a benchmark for the 3 main append delimiter techniques:
(benchmark with proper warmup and 100 rounds of 100,000 iterations)
"Append After"
"Append Before"
"Append Maybe"
I got the following results:
Aside from being the fastest, I am of the opinion that the "Append Maybe" implementation shows the intent of the code the best. That is usually more important than the fraction of nanoseconds gained per iteration.
I left the benchmark code here in case anyone wanted to try it on their platform. Please contribute your results above if you do so!
这是另一个解决方案:
Here is another solution:
stringBuilder.Remove(stringBuilder.Length - 1, 1);
stringBuilder.Remove(stringBuilder.Length - 1, 1);
如果您不想使用
StringJoiner
,这是对 @superpupervlad 技术的一个小改进(对于大型列表有很好的增益),它减少了分配的数量。If you don't want to use
StringJoiner
, here's a small improvement on the @superpupervlad technique (with a good gain for large lists), which reduces the number of assignments.更简单和紧凑的解决方案只需要对代码进行少量修改。
A much more simple and compact solution just requires a small modification to your code.
其他人指出了
deleteCharAt
方法,但这里有另一种替代方法:或者,使用
Joiner
来自 Guava :)从 Java 8 开始,
StringJoiner
是标准 JRE 的一部分。Others have pointed out the
deleteCharAt
method, but here's another alternative approach:Alternatively, use the
Joiner
class from Guava :)As of Java 8,
StringJoiner
is part of the standard JRE.另一个简单的解决方案是:
一个更复杂的解决方案:
上述解决方案假设 sb.length() > 。 0 ...即有一个“最后一个字符”需要删除。如果您无法做出该假设,和/或无法处理假设不正确时会发生的异常,那么首先检查 StringBuilder 的长度;例如
或
Another simple solution is:
A more complicated solution:
The above solution assumes that
sb.length() > 0
... i.e. there is a "last character" to remove. If you can't make that assumption, and/or you can't deal with the exception that would ensue if the assumption is incorrect, then check the StringBuilder's length first; e.g.or
从 Java 8 开始,String 类有一个静态方法(它们都是接口,因此类似于
加入
。第一个参数是每对字符串之间所需的字符串,第二个参数是 IterableList
> 有效,所以你可以这样做:同样在 Java 8 中,你可以使用新的
StringJoiner
类,适用于您希望在将完整的元素列表放入其中之前开始构造字符串的情况。As of Java 8, the String class has a static method
join
. The first argument is a string that you want between each pair of strings, and the second is anIterable<CharSequence>
(which are both interfaces, so something likeList<String>
works. So you can just do this:Also in Java 8, you could use the new
StringJoiner
class, for scenarios where you want to start constructing the string before you have the full list of elements to put in it.只需获取最后一个字符出现的位置即可。
由于
lastIndexOf
将执行反向搜索,并且您知道它会在第一次尝试时找到,因此性能在这里不会成为问题。编辑
由于我不断地提出我的答案(谢谢大家
Just get the position of the last character occurrence.
Since
lastIndexOf
will perform a reverse search, and you know that it will find at the first try, performance won't be an issue here.EDIT
Since I keep getting ups on my answer (thanks folks ????), it is worth regarding that:
On Java 8 onward it would just be more legible and explicit to use StringJoiner.
It has one method for a simple separator, and an overload for prefix and suffix.
Examples taken from here: example
Example using simple separator:
Output:
Example with suffix and prefix:
Output