Java: 使用 StringBuilder 在开头插入

例如,我只能用 String 来做这件事:

String str="";
for(int i=0;i<100;i++){
str=i+str;
}

有没有一种使用 StringBuilder 实现这一点的方法? 谢谢。

199523 次浏览
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0, Integer.toString(i));
}

警告: 这违背了 StringBuilder的宗旨,但它可以完成您的要求。


更好的技术 (尽管还不是很理想) :

  1. 反转要插入的 每个人字符串。
  2. 将每个字符串附加到 StringBuilder
  3. 完成后反转 完整的 StringBuilder

这将使 O (N2)溶液变成 O (N)溶液。

you can use strbuilder.insert(0,i);

也许我遗漏了一些东西,但是你想要一个字符串,看起来像这样,"999897969594...543210",对吗?

StringBuilder sb = new StringBuilder();
for(int i=99;i>=0;i--){
sb.append(String.valueOf(i));
}

This thread is quite old, but you could also think about a recursive solution passing the StringBuilder to fill. This allows to prevent any reverse processing etc. Just need to design your iteration with a recursion and carefully decide for an exit condition.

public class Test {


public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
doRecursive(sb, 100, 0);
System.out.println(sb.toString());
}


public static void doRecursive(StringBuilder sb, int limit, int index) {
if (index < limit) {
doRecursive(sb, limit, index + 1);
sb.append(Integer.toString(index));
}
}
}

作为一种替代解决方案,您可以使用 LIFO 结构(比如堆栈)来存储所有字符串,完成后只需将它们全部取出并放入 StringBuilder 中。它自然地颠倒放置在其中的项(字符串)的顺序。

Stack<String> textStack = new Stack<String>();
// push the strings to the stack
while(!isReadingTextDone()) {
String text = readText();
textStack.push(text);
}
// pop the strings and add to the text builder
String builder = new StringBuilder();
while (!textStack.empty()) {
builder.append(textStack.pop());
}
// get the final string
String finalText =  builder.toString();

I had a similar requirement when I stumbled on this post. I wanted a fast way to build a String that can grow from both sides ie. add new letters on the front as well as back arbitrarily. I know this is an old post, but it inspired me to try out a few ways to create strings and I thought I'd share my findings. I am also using some Java 8 constructs in this, which could have optimised the speed in cases 4 and 5.

Https://gist.github.com/sidwagz/e41e836dec65ff24f78afdf8669e6420

上面的 Gist 包含了任何人都可以运行的详细代码。 在这里我采取了一些增长字符串的方法: 1)给 StringBuilder 添加,2)在 StringBuilder 前面插入,如@Mehrdad 所示,3)部分地从 StringBuilder 的前面和末尾插入,4)使用一个列表从结尾添加,5)使用一个 Deque 从结尾添加。

// Case 2
StringBuilder build3 = new StringBuilder();
IntStream.range(0, MAX_STR)
.sequential()
.forEach(i -> {
if (i%2 == 0) build3.append(Integer.toString(i)); else build3.insert(0, Integer.toString(i));
});
String build3Out = build3.toString();




//Case 5
Deque<String> deque = new ArrayDeque<>();
IntStream.range(0, MAX_STR)
.sequential()
.forEach(i -> {
if (i%2 == 0) deque.addLast(Integer.toString(i)); else deque.addFirst(Integer.toString(i));
});


String dequeOut = deque.stream().collect(Collectors.joining(""));

我将专注于前面附加的案件即。案例2和案例5。StringBuilder 的实现在内部决定了内部缓冲区的增长方式,除了在前端附加的情况下将所有缓冲区从左向右移动限制了速度之外。如@Mehrdad 所示,直接插入到 StringBuilder 的前端所花费的时间会增长到非常高的值,如果需要的字符串长度小于90k 个字符(这仍然很多) ,那么前端插入将构建一个字符串,其时间与通过在结尾附加来构建一个长度相同的字符串所花费的时间相同。我想说的是,时间的惩罚确实是巨大的,但只有当你必须建立真正巨大的字符串。我们可以使用 deque 并将最后的字符串连接起来,如我的示例所示。但是 StringBuilder 对于阅读和编码来说更加直观一些,对于较小的字符串来说,这种损失并不重要。

实际上情况2的性能要比情况1快得多,我似乎不太明白。我假设 StringBuilder 中内部缓冲区的增长在前追加和后追加的情况下是相同的。我甚至将最小堆设置为非常大的数量,以避免堆增长的延迟,如果这会起到一定作用的话。也许有人谁有更好的理解可以在下面评论。

Difference Between String, StringBuilder And StringBuffer Classes
String
String is immutable ( once created can not be changed )object. The object created as a
String is stored in the Constant String Pool.
Every immutable object in Java is thread-safe, which implies String is also thread-safe. String
can not be used by two threads simultaneously.
String once assigned can not be changed.
StringBuffer
StringBuffer is mutable means one can change the value of the object. The object created
through StringBuffer is stored in the heap. StringBuffer has the same methods as the
StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread
safe .
Due to this, it does not allow two threads to simultaneously access the same method. Each
method can be accessed by one thread at a time.
But being thread-safe has disadvantages too as the performance of the StringBuffer hits due
to thread-safe property. Thus StringBuilder is faster than the StringBuffer when calling the
same methods of each class.
String Buffer can be converted to the string by using
toString() method.


StringBuffer demo1 = new StringBuffer("Hello") ;


// The above object stored in heap and its value can be changed.
/
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder is the same as the StringBuffer, that is it stores the object in heap and it can also
be modified. The main difference between the StringBuffer and StringBuilder is
that StringBuilder is also not thread-safe.
StringBuilder is fast as it is not thread-safe.
/
// The above object is stored in the heap and its value can be modified
/
// Above statement is right as it modifies the value which is allowed in the StringBuilder

可以将 insert 方法与偏移量一起使用。 偏移量设置为“0”意味着您正在追加到 StringBuilder 的前端。

StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0,i);
}

注意 : 由于 insert 方法接受所有类型的原语,所以可以使用 int、 long、 char []等。

这个怎么样:

StringBuilder builder = new StringBuilder();
for(int i=99;i>=0;i--){
builder.append(Integer.toString(i));
}
builder.toString();

或者

StringBuilder builder = new StringBuilder();
for(int i=0;i<100;i++){
builder.insert(0, Integer.toString(i));
}
builder.toString();

But with this, you are making the operation O(N^2) instead of O(N).

来自 java 文档的片段:

将 Object 参数的字符串表示形式插入到 字符序列。整体效果完全如同第二个 参数被该方法转换为字符串 字符串的字符 插入到这个字符序列的指示偏移量。