java: başlangıca eklemek için StringBuilder kullanın


Yanıtlar:


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

Uyarı: Amacını bozarStringBuilder , ancak istediğinizi yapar.


Daha iyi teknik (yine de ideal olmasa da):

  1. Eklemek istediğiniz her dizeyi ters çevirin .
  2. Append bir her dize StringBuilder.
  3. İşiniz bittiğinde tamamını tersine çevirin StringBuilder.

Bu bir O ( n ²) çözümünü O ( n ) 'ye çevirecektir .


2
... AbstractStringBuildereklenenler için yer bulmak için tüm içeriği ekleme dizininin ötesine taşımayı sağlar. Ancak bu bir uygulama detayıdır, prensiplerden biri değildir.
entonio

1
@entonio: Gerçekten, ama bu çok kritik bir detay. :)
user541686

1
Anlıyorum, o halde StringBuilder kullanmamam gerekiyor gibi görünüyor, Çok teşekkürler
user685275

@ user685275: Evet, geriye doğru eklemeye ihtiyacınız varsa, o zaman gerçekten dizenin başına eklenebilecek bir şeye ihtiyacınız var. Sanırım en kolay çözüm yukarıdaki tekniktir (her şeyi iki kez tersine çevirmek), ancak muhtemelen char dizileriyle daha iyi bir sınıf oluşturabilirsin ("deque" lere bakmak isteyebilirsin).
user541686

1
@rogerdpack: Amaç değil mekanizma olduğunu söyleyebilirim. Amaç, dizge işlemeden asimptotik olarak daha hızlı olmaktır, eğer yanlış kullanırsanız bu olmayacaktır.
user541686

32

kullanabilirsiniz strbuilder.insert(0,i);


2
Bu neden bu kadar çok beğenildi! Sınıf doğru tanımlanmadı - yalnızca yöntem çağrısının imzası!
JGFMK

13

Belki bir şeyi kaçırıyorum ama bunun gibi görünen bir String ile bitmek istiyorsun, değil mi "999897969594...543210"?

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

Tuhaf, bu gönderi, döngü üzerinde akıllıca manipülasyon yaparak çözüm sağlarken fazla oy almamış,
nom-mon-ir

1
@ nom-mon-ir o sadece String'i ters çeviriyor. Sola nasıl ekleneceğine cevap vermiyor.
Raymond Chenon

İstenilen etkiyi sağlar.
Speck

StringBuilder'ın gerçek potansiyelini kullanan başlangıçta ekleme yapmanın bir yolunu kesmek yerine bu yaklaşımı kullanabileceğiniz durumlar olabileceğini düşünüyorum. Her neyse, döngüyü tersine çeviremeyeceğiniz durumlar var, bu yüzden diğer cevaplara da ihtiyacınız var.
PhoneixS

7

Alternatif bir çözüm olarak, tüm dizeleri depolamak için bir LIFO yapısı (bir yığın gibi) kullanabilirsiniz ve işiniz bittiğinde hepsini çıkarın ve StringBuilder'a koyun. İçine yerleştirilen öğelerin (dizelerin) sırasını doğal olarak tersine çevirir.

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
ArrayDequeyerine kullanılmalıdır Stack. "Daha eksiksiz ve tutarlı bir LIFO yığın işlemleri seti, {@link Deque} arayüzü ve bu sınıfa tercih edilerek kullanılması gereken uygulamaları tarafından sağlanır."
Luna

5

Bu iş parçacığı oldukça eskidir, ancak StringBuilder'ı doldurmak için geçiren özyinelemeli bir çözüm de düşünebilirsiniz. Bu, herhangi bir ters işlemeyi önlemeye izin verir. Sadece yinelemenizi bir özyineleme ile tasarlamanız ve bir çıkış durumuna dikkatlice karar vermeniz gerekir.

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

Bu yazıya tökezlediğimde benzer bir şartım vardı. Her iki taraftan da büyüyebilen bir String oluşturmanın hızlı bir yolunu istedim, yani. keyfi olarak öne ve arkaya yeni harfler ekleyin. Bunun eski bir gönderi olduğunu biliyorum, ancak dizeler oluşturmanın birkaç yolunu denemem için bana ilham verdi ve bulgularımı paylaşacağımı düşündüm. Ayrıca, 4 ve 5 numaralı durumlarda hızı optimize edebilecek bazı Java 8 yapıları kullanıyorum.

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

Yukarıdaki Özet, herkesin çalıştırabileceği ayrıntılı bir koda sahiptir. Bunda ipleri büyütmenin birkaç yolunu seçtim; 1) StringBuilder'a ekleyin, 2) @Mehrdad tarafından gösterildiği gibi StringBuilder'ın önüne ekleyin, 3) StringBuilder'ın önünden ve sonundan kısmen ekleyin, 4) Sondan eklemek için bir liste kullanmak, 5) ön taraftan ekleyin.

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

Sadece öndeki ek durumlara odaklanacağım yani. durum 2 ve durum 5. StringBuilder uygulaması dahili olarak dahili tamponun nasıl büyüdüğüne karar verir; bu, ön ekleme durumunda tüm tamponun soldan sağa taşınmasının yanı sıra hızı sınırlar. StringBuilder'ın doğrudan önüne eklerken geçen süre, @Mehrdad tarafından gösterildiği gibi gerçekten yüksek değerlere ulaşırken, ihtiyaç yalnızca 90k karakterden daha az uzunlukta dizelere sahip olmaksa (ki bu hala çok fazladır), ön ekleme Sonuna ekleyerek aynı uzunlukta bir String oluşturmak için gereken zamanda bir String oluşturun. Demek istediğim, zaman cezasının gerçekten tekme attığı ve çok büyük olduğu, ancak yalnızca gerçekten çok büyük dizeler oluşturmanız gerektiğinde. Benim örneğimde gösterildiği gibi bir deque kullanabilir ve sondaki dizeleri birleştirebilir.

Aslında durum 2'nin performansı, durum 1'den çok daha hızlı, ki bunu anlamıyorum. StringBuilder'daki dahili tampon için büyümenin ön ekleme ve arka ekleme durumunda aynı olacağını varsayıyorum. Hatta bir rol oynamış olsaydı, yığın büyümesinde gecikmeyi önlemek için minimum yığını çok büyük bir miktara ayarladım. Belki daha iyi anlayan biri aşağıya yorum yapabilir.


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'a hoş geldiniz. Lütfen kodun ne yaptığı ve sorunu nasıl çözdüğü hakkında soruya bir açıklama ekleyin.
bad_coder

1

Ofset ile ekleme yöntemini kullanabilirsiniz. ofset olarak '0' olarak ayarlandığında, StringBuilder'ınızın önüne eklediğiniz anlamına gelir.

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

NOT : ekleme yöntemi tüm ilkel türlerini kabul ettiğinden, int, long, char [] vb. İçin kullanabilirsiniz.


0

Peki ya:

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

VEYA

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

Ancak bununla O (N) yerine O (N ^ 2) işlemini yapıyorsunuz.

Java dokümanlarından pasaj:

Object bağımsız değişkeninin dize gösterimini bu karakter dizisine ekler. Genel etki, tıpkı ikinci bağımsız değişken, yöntem tarafından bir dizeye dönüştürülmüş String.valueOf(Object)ve bu dizenin karakterleri daha sonra belirtilen ofsette bu karakter dizisine eklenmiş gibidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.