java:StringBuilderを使用して最初に挿入します


94

これはStringでしかできませんでした。例:

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

StringBuilderでこれを実現する方法はありますか?ありがとう。

回答:


187
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)を。


2
...AbstractStringBuilder挿入されたコンテンツのスペースを見つけるために、すべてのコンテンツを挿入インデックスを超えて移動するためです。ただし、これは実装の詳細であり、原則の1つではありません。
entonio

1
@entonio:確かに、しかしそれは非常に重要な詳細です。:)
user541686

1
なるほど、StringBuilderを使用するべきではないようです。
どうも

@ user685275:ええ、逆挿入が必要な場合は、文字列の先頭に挿入できるものが本当に必要です。最も簡単な解決策は上記の手法(2回逆にする)だと思いますが、char配列を使用して独自のクラスを作成することもできます(「deque」を調べたい場合があります)。
user541686

1
@rogerdpack:それがメカニズムであり、目的ではないと思います。目的は、文字列操作よりも漸近的に高速になることです。これは、間違って使用した場合には起こりません。
user5416 8619

32

あなたが使用することができます strbuilder.insert(0,i);


2
なぜこれほど多くのいいねを獲得したのですか?クラスが正しく定義されていません-メソッド呼び出しのシグネチャのみです!
JGFMK

13

何かが足りないかもしれませんが、次のような文字列を作成したいのですが"999897969594...543210"、正しいですか?

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

奇妙なことに、この投稿は、ループの巧妙な操作によって解決策を提供している間、あまり投票されませんでした
nom-mon-ir 2014年

1
@ nom-mon-ir彼は文字列を逆にしているだけです。左側の追加方法には答えていません。
レイモンドシェノン2015年

目的の効果を実現します。
スペック2015年

StringBuilderの真の可能性を利用して、最初に挿入を行う方法をハックする代わりに、このアプローチを使用できる場合があると思います。とにかく、ループを逆にできない場合があるので、他の答えも必要です。
phoneixS 2018

7

別の解決策として、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();

4
ArrayDequeの代わりに使用する必要がありStackます。「より完全で一貫性のあるLIFOスタック操作のセットは、{@ link Deque}インターフェイスとその実装によって提供されます。これは、このクラスよりも優先して使用する必要があります。」
Luna

5

このスレッドはかなり古いですが、StringBuilderを渡してfillする再帰的なソリューションについて考えることもできます。これにより、逆処理などを防ぐことができます。再帰を使用して反復を設計し、終了条件を慎重に決定する必要があります。

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

3

この投稿に出くわしたときも、同様の要件がありました。両側から成長できる文字列をすばやく作成する方法が必要でした。前面と背面に任意に新しい文字を追加します。これが古い投稿であることは知っていますが、文字列を作成するいくつかの方法を試してみるようになり、発見したことを共有したいと思いました。また、これでいくつかのJava 8構造を使用しています。これにより、ケース4と5で速度が最適化された可能性があります。

https://gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e6420

上記の要点には、誰でも実行できる詳細なコードがあります。私はこれで弦を伸ばすいくつかの方法を取りました。1)StringBuilderに追加、2)@Mehrdadで示されるようにStringBuilderの前に挿入、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文字未満の長さの文字列のみが必要な場合(これはまだ多いです)、前面の挿入は最後に追加して同じ長さの文字列を作成するのと同じ時間に文字列を作成します。私が言っているのは、時間のペナルティは確かにキックして巨大であるということですが、それはあなたが本当に巨大なストリングを構築しなければならないときだけです。私の例に示すように、両端キューを使用して、最後に文字列を結合することができます。

実際、ケース2のパフォーマンスはケース1よりもはるかに高速ですが、私には理解できないようです。StringBuilderの内部バッファーの増加は、フロントアペンドとバックアペンドの場合と同じであると思います。ヒープの成長が遅れないように、最小ヒープを非常に大きな量に設定しました。たぶん、よりよく理解している人が以下にコメントすることができます。


1
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

1
stackoverflowへようこそ。コードの機能と問題の解決方法の説明を質問に含めてください。
bad_coder

1

オフセット付きの挿入メソッドを使用できます。オフセットを「0」に設定すると、StringBuilderの前に追加することを意味します。

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

:insertメソッドはすべてのタイプのプリミティブを受け入れるため、int、long、char []などに使用できます。


0

どうですか:

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)ではなくO(N ^ 2)の操作を行うことになります。

Javaドキュメントからのスニペット:

Object引数の文字列表現をこの文字シーケンスに挿入します。全体的な効果は、2番目の引数がメソッドによって文字列に変換され、String.valueOf(Object)その文字列の文字が指定されたオフセットでこの文字シーケンスに挿入された場合とまったく同じ です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.