Я мог сделать это только с помощью String, например:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Есть ли способ добиться этого с помощью StringBuilder? Спасибо.
Я мог сделать это только с помощью String, например:
String str="";
for(int i=0;i<100;i++){
str=i+str;
}
Есть ли способ добиться этого с помощью StringBuilder? Спасибо.
Ответы:
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0, Integer.toString(i));
}
Предупреждение: это противоречит целиStringBuilder
, но делает то, что вы просили.
Лучшая техника (хотя и не идеальная):
StringBuilder
.StringBuilder
, когда вы закончите.Это превратит решение O ( n ²) в O ( n ).
ты можешь использовать strbuilder.insert(0,i);
Возможно, я что-то упустил, но вы хотите получить строку, которая выглядит так "999897969594...543210"
, верно?
StringBuilder sb = new StringBuilder();
for(int i=99;i>=0;i--){
sb.append(String.valueOf(i));
}
В качестве альтернативного решения вы можете использовать структуру 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();
ArrayDeque
следует использовать вместо Stack
. «Более полный и последовательный набор операций стека LIFO обеспечивается интерфейсом {@link Deque} и его реализациями, которые следует использовать вместо этого класса»,
Этот поток довольно старый, но вы также можете подумать о рекурсивном решении, передающем 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));
}
}
}
Когда я наткнулся на этот пост, у меня было подобное требование. Мне нужен был быстрый способ построить строку, которая могла бы расти с обеих сторон, т.е. произвольно добавлять новые буквы как спереди, так и сзади. Я знаю, что это старый пост, но он вдохновил меня попробовать несколько способов создания строк, и я решил поделиться своими выводами. Я также использую здесь некоторые конструкции Java 8, которые могли бы оптимизировать скорость в случаях 4 и 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 внутренне решает, как будет расти внутренний буфер, что помимо перемещения всего буфера слева направо в случае добавления спереди ограничивает скорость. Хотя время, затрачиваемое на вставку непосредственно в начало StringBuilder, увеличивается до действительно высоких значений, как показано @Mehrdad, если необходимо иметь только строки длиной менее 90 тыс. Символов (что все еще много), передняя вставка будет построить String за то же время, что и для создания String такой же длины, добавив в конце. Я говорю о том, что временное наказание действительно здорово и очень велико, но только тогда, когда вам нужно строить действительно огромные струны. Можно использовать двухстороннюю очередь и присоединить строки в конце, как показано в моем примере.
На самом деле производительность для случая 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
Вы можете использовать метод вставки со смещением. поскольку смещение, установленное на '0', означает, что вы добавляете в начало своего StringBuilder.
StringBuilder sb = new StringBuilder();
for(int i=0;i<100;i++){
sb.insert(0,i);
}
ПРИМЕЧАНИЕ : поскольку метод вставки принимает все типы примитивов, вы можете использовать его для 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();
Но при этом вы выполняете операцию O (N ^ 2) вместо O (N).
Фрагмент из java-документов:
Вставляет строковое представление аргумента Object в эту последовательность символов. Общий эффект такой же, как если бы второй аргумент был преобразован в строку методом
String.valueOf(Object)
, а символы этой строки затем были вставлены в эту последовательность символов с указанным смещением.
AbstractStringBuilder
перемещать все содержимое за пределы индекса вставки, чтобы найти место для вставленных. Однако это деталь реализации, а не принцип.