java:使用StringBuilder在开头插入

发布于 2024-11-06 11:42:12 字数 166 浏览 4 评论 0原文

我只能用 String 来做到这一点,例如:

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

有没有办法用 StringBuilder 来实现这一点?谢谢。

I could only do this with String, for example:

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

Is there a way to achieve this with StringBuilder? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

悲凉≈ 2024-11-13 11:42:12
// DO NOT DO THIS. It is quadratic-time!
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
    sb.insert(0, Integer.toString(i));
}

警告: 它违背了 StringBuilder 的目的,但它执行了您所要求的操作。


更好的技术(尽管仍然不理想):

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

这会将 O(n²) 解决方案变成 O(n)。

// DO NOT DO THIS. It is quadratic-time!
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
    sb.insert(0, Integer.toString(i));
}

Warning: It defeats the purpose of StringBuilder, but it does what you asked.


Better technique (although still not ideal):

  1. Reverse each string you want to insert.
  2. Append each string to a StringBuilder.
  3. Reverse the entire StringBuilder when you're done.

This will turn an O(n²) solution into O(n).

小镇女孩 2024-11-13 11:42:12

您可以使用strbuilder.insert(0,i);

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

玻璃人 2024-11-13 11:42:12

也许我遗漏了一些东西,但你想得到一个看起来像这样的字符串,“999897969594...543210”,对吗?

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

Maybe I'm missing something but you want to wind up with a String that looks like this, "999897969594...543210", correct?

StringBuilder sb = new StringBuilder();
for(int i=99;i>=0;i--){
    sb.append(String.valueOf(i));
}
满意归宿 2024-11-13 11:42:12

作为替代解决方案,您可以使用 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();

As an alternative solution you can use a LIFO structure (like a stack) to store all the strings and when you are done just take them all out and put them into the StringBuilder. It naturally reverses the order of the items (strings) placed in it.

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();
鸠书 2024-11-13 11:42:12

该线程相当古老,但您也可以考虑传递 StringBuilder 来填充的递归解决方案。这可以防止任何逆向处理等。只需使用递归设计迭代并仔细决定退出条件。

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));
        }
    }
}

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));
        }
    }
}
饭团 2024-11-13 11:42:12

您可以使用带有偏移量的插入方法。
因为偏移量设置为“0”意味着您要附加到 StringBuilder 的前面。

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

注意
由于 insert 方法接受所有类型的基元,因此您可以使用 int、long、char[] 等。

You can use the insert method with the offset.
as offset set to '0' means you are appending to the front of your StringBuilder.

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

NOTE:
as the insert method accept all types of primitives, you can use for int, long, char[] etc.

云之铃。 2024-11-13 11:42:12

当我偶然发现这篇文章时,我也有类似的要求。我想要一种快速的方法来构建可以从两侧生长的字符串,即。在正面和背面任意添加新字母。我知道这是一篇旧文章,但它激发了我尝试一些创建字符串的方法,我想我应该分享我的发现。我还在其中使用了一些 Java 8 构造,这可以优化案例 4 和 5 中的速度

。 noreferrer">https://gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e6420

上面的要点有任何人都可以运行的详细代码。
我在这方面采取了几种增长字符串的方法; 1)追加到 StringBuilder,2)插入到 StringBuilder 的前面,如 @Mehrdad 所示,3)从 StringBuilder 的前面和末尾部分插入,4)使用列表从末尾追加,5)使用双端队列从前面追加。

// 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 的实现在内部决定内部缓冲区如何增长,除了在前面追加的情况下将所有缓冲区从左向右移动之外还限制了速度。虽然直接插入到 StringBuilder 前面所花费的时间会增长到非常高的值,如 @Mehrdad 所示,如果只需要长度小于 90k 个字符的字符串(这仍然很多),则前面的插入将构建一个字符串的时间与通过在末尾附加构建相同长度的字符串的时间相同。我想说的是,时间损失确实很大,但只有当你必须构建非常巨大的字符串时。可以使用双端队列并在末尾连接字符串,如我的示例所示。但 StringBuilder 的阅读和编码更加直观,而且对于较小的字符串来说,这种损失并不重要。

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

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

The Gist above has the detailed code that anyone can run.
I took few ways of growing strings in this; 1) Append to StringBuilder, 2) Insert to front of StringBuilder as as shown by @Mehrdad, 3) Partially insert from front as well as end of the StringBuilder, 4) Using a list to append from end, 5) Using a Deque to append from the front.

// 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(""));

I'll focus on the front append only cases ie. case 2 and case 5. The implementation of StringBuilder internally decides how the internal buffer grows, which apart from moving all buffer left to right in case of front appending limits the speed. While time taken when inserting directly to the front of the StringBuilder grows to really high values, as shown by @Mehrdad, if the need is to only have strings of length less than 90k characters (which is still a lot), the front insert will build a String in the same time as it would take to build a String of the same length by appending at the end. What I am saying is that time time penalty indeed kicks and is huge, but only when you have to build really huge strings. One could use a deque and join the strings at the end as shown in my example. But StringBuilder is a bit more intuitive to read and code, and the penalty would not matter for smaller strings.

Actually the performance for case 2 is much faster than case 1, which I don't seem to understand. I assume the growth for the internal buffer in StringBuilder would be the same in case of front append and back append. I even set the minimum heap to a very large amount to avoid delay in heap growth, if that would have played a role. Maybe someone who has a better understanding can comment below.

时光清浅 2024-11-13 11:42:12
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
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
初相遇 2024-11-13 11:42:12

怎么样:

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();

但是有了这个,您将进行 O(N^2) 操作而不是 O(N)。

来自 java 文档的片段:

将对象参数的字符串表示形式插入到此中
字符序列。整体效果和第二个一模一样
参数通过方法转换为字符串
String.valueOf(Object),然后该字符串的字符
插入到此字符序列中指定的偏移量处。

How about:

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

OR

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).

Snippet from java docs:

Inserts the string representation of the Object argument into this
character sequence. The overall effect is exactly as if the second
argument were converted to a string by the method
String.valueOf(Object), and the characters of that string were then
inserted into this character sequence at the indicated offset.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文