StringBuilder如何去除字符串空格?

38

我们如何对 StringBuilder 值进行修剪,而不会使用 StringBuilder.toString().trim() 导致每次修剪调用都创建一个新的 String 和/或一个新的 StringBuilder 实例所带来的开销?


1
我可以问一下,为什么你不想使用 StringBuilder.toString().trim() 吗? - Kazekage Gaara
2
实际上,我正在一个循环中,需要将这个 StringBuilder 字符串与许多其他值进行比较,因此如果每次调用 StringBuilder.toString().trim(),它都会创建一个新的实例,而我不想每次都创建一个新的字符串对象。 - Pramod Kumar
你可以根据需要多次使用 toString().trim()。请编辑您的问题并添加先前的评论以进行澄清。 - Martín Schonaker
如果它确实有一个trim()方法,那么可能会有人问为什么?这不是一个真正的问题。 - user207421
@EJP - 我该如何解锁这个问题?我想添加修剪 StringBuilder 代码。 - Erran Morad
我编写了一些代码来修剪一个 StringBuilder,并使用测试输入来检查正确性- https://dev59.com/LG435IYBdhLWcg3wyzQJ#27417960 - Erran Morad
5个回答

26
为什么StringBuilder没有trim()方法?
  1. 这是它设计的方式,你可以问问设计者。
  2. 因为很少有人需要它。
  3. 因为String的trim()语义和签名不适合可变字符串,虽然这是有争议的。
总之,答案与解决问题无关。
如何修剪StringBuilder值?
最简单的方法是使用StringBuilder.toString().trim()...
我不想使用StringBuilder.toString().trim()。
那么你需要做的就是在内部匹配和删除前导和尾随空格,就像trim()一样。由于StringBuilder API没有正则表达式支持,所以您需要通过从前向后遍历字符并从后往前结束来执行此操作,以查看哪些字符需要被删除等等。
您确定不愿意选择简单的方法吗?如果不是,这个Q&A有一些示例实现、分析、基准测试等等: 最后,您可以实现自己的StringBuilder类的变体,该类具有trim()方法。您可能需要使用不同的内部表示形式,以便删除起始字符的操作不复制字符。(虽然我不建议这样做...但如果您对trim()有实际上的强烈需求,这是一个选项。)

实际上我现在需要一个循环,要将此 StringBuilder 字符串与许多其他值进行比较,因此如果每次调用 StringBuilder.toString().trim() ,它都会创建一个新实例,我不想每次都创建一个新的字符串对象。

另一方面,从 StringBuilder 的开头删除字符需要复制其余所有字符。

也许你最好一开始就将完整的 StringBuilder 转换为 String,然后当你使用 trim()substring() 等方法时,你就不会复制字符2


1 - 对于那些声称这样说“没有建设性”的人,替代方案是假装我们“在场”时听到了设计决策并参与了辩论。但这是虚假的。坦白地说,指出没有人知道答案,并且不假装知道,是有意义的。为什么?因为很多读者可能不知道当时的 Java 设计过程是不透明的。

2 - 在 Java 7 之前,这些方法通过创建一个新的字符串来工作,该字符串共享原始 String 的支持数组... 因此,你只需要复制字符串的控制信息。在 Java 7 中,它们改变了 trimsubstring 的实现方式,使其使用复制支持数组的子数组的 String 构造函数。


6
我不知道你想达到什么目的,但如果你担心性能问题,也许你可以在将字符串添加到StringBuilder时进行修剪。 stringbuilder.append(string.trim())

2
为什么 StringBuilder 没有 trim() 方法?
嗯... StringBuilder 就像 String 一样,只是它可以在创建后进行修改,否则与字符串相同。
如上链接所述,“StringBuilder 的主要操作是 append 和 insert 方法”。我想它们旨在支持可变字符串,就像 StringBuffer 一样。如果您可以通过对其他方法进行小调用,然后再使用所需的方法来完成任务,那么这有什么关系呢?为什么要在多个类中实现相同的功能。
我们如何修剪 StringBuilder 的值?
正如其他人所说,stringBuilder.toString().trim();
我不想使用 StringBuilder.toString().trim()。
嗯...这是选择的问题,有任何特定原因吗?

1
实际上,我正在一个循环中,在这个循环中,我必须将这个 StringBuilder 字符串与许多其他值进行比较,因此如果每次调用 StringBuilder.toString().trim(),它都会创建一个新的实例,而我不想每次都创建一个新的字符串对象。 - Pramod Kumar
иҮ·дҢүз”Ёж‚Ёи‡Ғе·±зљ„char[]和分隔符。жџӨзњ‹java.lang.Stringд»Әз ЃгЂ‚ - Martín Schonaker

0

您可以将 StringBuilder 实例转换为 string,然后对其进行修剪。

sb.toString().trim();//sb is stringBuilder Instance.

0

使用 StringBuilder.toString().trim(),但将其保存在变量中。

例如:

String myTrimmedString = myStringBuilder.toString().trim();

它没有trim()方法,因为使用不可变对象非常容易且有些更受欢迎。想象一下,一个线程正在修剪StringBuilder,而另一个线程正在向其中添加内容。想象一下这可能会在您的代码中引起的错误和怪异行为。


2
想象一条线程正在修剪 StringBuilder,而另一条线程正在向其追加内容。这种情况也可能发生在追加操作中,当一条线程正在追加某些内容而另一条线程正在追加其他内容时...那么在这种情况下怎么办?它也不应该支持追加操作。 - Pramod Kumar
@PramodKumar 我想象虚拟机只允许一个东西在同一时间写入char[]。然而,对读取施加同样的限制是荒谬的。在同时进行读写时,我猜测它会阻塞读取,使这成为无关问题。这完全取决于虚拟机的实现。trim()非常可能能够正常工作。这是一个假设性情况,以展示实现不可变对象可以更容易。并且它们使用更少的内存。 - iracigt
1
虽然你的解决方案是正确的,但你的理由完全错误。StringBuilder设计上不是线程安全的,所以正如Pramod Kumar所说,对它进行任何并发操作都是危险的。任何在多个线程中使用StringBuilder而没有对其进行同步的人都需要被开除。StringBuffer是StringBuilder的线程安全版本,因为它使用内部同步。*(StringBuilder被引入到Java中,用于只有一个线程会访问它的情况下,并且希望避免StringBuffer中同步的开销。)* - daiscog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接