Ich könnte das nur mit String machen, zum Beispiel:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Gibt es eine Möglichkeit, dies mit StringBuilder zu erreichen? Vielen Dank.
Ich könnte das nur mit String machen, zum Beispiel:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Gibt es eine Möglichkeit, dies mit StringBuilder zu erreichen? Vielen Dank.
Antworten:
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0, Integer.toString(i));
}
Warnung: Es macht den Zweck von zunichteStringBuilder
, aber es tut, was Sie gefragt haben.
Bessere Technik (obwohl immer noch nicht ideal):
StringBuilder
.StringBuilder
wenn Sie fertig sind.Dies wird wiederum eine O ( n ²) Lösung in O ( n ).
Sie können verwenden strbuilder.insert(0,i);
Vielleicht fehlt mir etwas, aber Sie möchten mit einem String enden, der so aussieht "999897969594...543210"
, richtig?
StringBuilder sb = new StringBuilder();
for(int i=99;i>=0;i--){
sb.append(String.valueOf(i));
}
Als alternative Lösung können Sie eine LIFO-Struktur (wie einen Stapel) verwenden, um alle Zeichenfolgen zu speichern. Wenn Sie fertig sind, nehmen Sie sie einfach heraus und fügen Sie sie in den StringBuilder ein. Es kehrt natürlich die Reihenfolge der darin platzierten Elemente (Zeichenfolgen) um.
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();
ArrayDeque
sollte anstelle von verwendet werden Stack
. "Ein vollständigerer und konsistenterer Satz von LIFO-Stapeloperationen wird durch die {@link Deque} -Schnittstelle und ihre Implementierungen bereitgestellt, die dieser Klasse vorgezogen werden sollten."
Dieser Thread ist ziemlich alt, aber Sie könnten auch über eine rekursive Lösung nachdenken, die den StringBuilder zum Füllen übergibt. Dies ermöglicht es, eine umgekehrte Verarbeitung usw. zu verhindern. Sie müssen lediglich Ihre Iteration mit einer Rekursion entwerfen und sorgfältig für eine Beendigungsbedingung entscheiden.
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));
}
}
}
Ich hatte eine ähnliche Anforderung, als ich über diesen Beitrag stolperte. Ich wollte einen schnellen Weg, um einen String zu bauen, der von beiden Seiten wachsen kann, dh. Fügen Sie beliebig neue Buchstaben auf der Vorder- und Rückseite hinzu. Ich weiß, dass dies ein alter Beitrag ist, aber er hat mich dazu inspiriert, einige Möglichkeiten zum Erstellen von Zeichenfolgen auszuprobieren, und ich dachte, ich würde meine Erkenntnisse teilen. Ich verwende hier auch einige Java 8-Konstrukte, die in den Fällen 4 und 5 die Geschwindigkeit hätten optimieren können.
https://gist.github.com/SidWagz/e41e836dec65ff24f78afdf8669e6420
Das obige Gist enthält den detaillierten Code, den jeder ausführen kann. Ich habe nur wenige Möglichkeiten gewählt, um die Saiten zu vergrößern. 1) An StringBuilder anhängen, 2) An die Vorderseite von StringBuilder einfügen, wie von @Mehrdad gezeigt, 3) Teilweise von vorne sowie am Ende des StringBuilder einfügen, 4) Verwenden einer Liste zum Anhängen von Ende an, 5) Verwenden einer Deque an von vorne anhängen.
// 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(""));
Ich werde mich auf die Vorderseite konzentrieren und nur Fälle anhängen, dh. Fall 2 und Fall 5. Die Implementierung von StringBuilder entscheidet intern darüber, wie der interne Puffer wächst, was abgesehen davon, dass der gesamte Puffer im Falle eines Frontanhangs von links nach rechts verschoben wird, die Geschwindigkeit begrenzt. Während die Zeit, die beim direkten Einfügen in die Vorderseite des StringBuilder benötigt wird, auf sehr hohe Werte ansteigt, wie von @Mehrdad gezeigt, wird die vordere Einfügung verwendet, wenn nur Zeichenfolgen mit einer Länge von weniger als 90.000 Zeichen benötigt werden (was immer noch viel ist) Erstellen Sie einen String in der gleichen Zeit, die zum Erstellen eines Strings mit derselben Länge erforderlich ist, indem Sie ihn am Ende anhängen. Was ich damit sagen will ist, dass die Zeitstrafe in der Tat tritt und riesig ist, aber nur, wenn man wirklich große Saiten bauen muss. Man könnte eine Deque verwenden und die Strings am Ende verbinden, wie in meinem Beispiel gezeigt.
Tatsächlich ist die Leistung für Fall 2 viel schneller als für Fall 1, was ich nicht zu verstehen scheine. Ich gehe davon aus, dass das Wachstum für den internen Puffer in StringBuilder im Fall von Front Append und Back Append gleich ist. Ich habe sogar den minimalen Heap auf einen sehr großen Wert festgelegt, um Verzögerungen beim Heap-Wachstum zu vermeiden, wenn dies eine Rolle gespielt hätte. Vielleicht kann jemand, der ein besseres Verständnis hat, unten einen Kommentar abgeben.
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
Sie können die Einfügemethode mit dem Versatz verwenden. Wenn der Versatz auf '0' gesetzt ist, werden Sie an die Vorderseite Ihres StringBuilder angehängt.
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0,i);
}
HINWEIS : Da die Einfügemethode alle Arten von Grundelementen akzeptiert, können Sie sie für int, long, char [] usw. verwenden.
Wie wäre es mit:
StringBuilder builder = new StringBuilder();
for(int i=99;i>=0;i--){
builder.append(Integer.toString(i));
}
builder.toString();
ODER
StringBuilder builder = new StringBuilder();
for(int i=0;i<100;i++){
builder.insert(0, Integer.toString(i));
}
builder.toString();
Aber damit machen Sie die Operation O (N ^ 2) anstelle von O (N).
Ausschnitt aus Java-Dokumenten:
Fügt die Zeichenfolgendarstellung des Object-Arguments in diese Zeichenfolge ein. Der Gesamteffekt ist genau so, als ob das zweite Argument von der Methode in eine Zeichenfolge konvertiert
String.valueOf(Object)
wurde und die Zeichen dieser Zeichenfolge dann mit dem angegebenen Versatz in diese Zeichenfolge eingefügt wurden.
AbstractStringBuilder
gesamte Inhalt über den Einfügeindex hinaus verschoben wird, um Platz für die eingefügten zu finden. Dies ist jedoch ein Implementierungsdetail, kein Prinzip.