web-dev-qa-db-ja.com

java:StringBuilderを使用して先頭に挿入する

私はこれを文字列でのみ行うことができました、例えば:

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

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

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

警告:それはStringBuilderの目的を無効にしますが、あなたが要求したことはします。


より良いテクニック(まだ理想的ではありませんが):

  1. 挿入したい文字列を逆each文字列。
  2. Append各文字列をStringBuilderに追加します。
  3. 完了したら、entireStringBuilderを反転します。

これにより、O(n²)解がO(nに変換されます。 )。

161
Mehrdad

strbuilder.insert(0,i);を使用できます

27
ratchet freak

たぶん私は何かを見逃しているかもしれませんが、あなたはこのように見える文字列、"999897969594...543210"、正しいもので終わらせたいですか?

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

代替ソリューションとして、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();
6
Vasile Jureschi

このスレッドは非常に古いものですが、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));
        }
    }
}
4
Benjamin

この投稿につまずいたときも、同様の要件がありました。私は両方の側から成長することができる文字列を構築するための高速な方法が欲しかった。前面と背面に新しい文字を任意に追加します。これが古い投稿であることは知っていますが、文字列を作成するいくつかの方法を試してみようと思い、結果を共有したいと思いました。また、これでいくつかのJava 8コンストラクトを使用しています。これにより、ケース4および5で速度が最適化された可能性があります。

https://Gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e642

上記のGistには、誰でも実行できる詳細なコードがあります。これで文字列を成長させるいくつかの方法を取りました。 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文字未満の文字列のみを保持する必要がある場合(それでも多くの場合)、前面挿入は最後に追加して同じ長さの文字列を作成するのと同じ時間で文字列を作成します。私が言っていることは、時間のペナルティが実際にキックされ、巨大であるが、本当に巨大な文字列を構築する必要がある場合のみです。私の例に示すように、両端キューを使用して、最後に文字列を結合できます。ただし、StringBuilderは読み取りとコーディングが少し直感的であり、小さな文字列の場合はペナルティは問題になりません。

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

2
Siddharth Wagle