자바 : StringBuilder를 사용하여 처음에 삽입


95

예를 들어 다음과 같이 String으로 만이 작업을 수행 할 수 있습니다.

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

StringBuilder로 이것을 달성하는 방법이 있습니까? 감사.

답변:


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

경고 : 의 목적에 위배StringBuilder 되지만 요청한대로 수행됩니다.


더 나은 기술 (아직 이상적이지는 않지만) :

  1. 각각 삽입 할 문자열입니다.
  2. 추가 A와 각 문자열을 StringBuilder.
  3. 전체를 StringBuilder 작업을 완료 할 때.

이것은 O ( n ²) 솔루션을 O ( n ) 으로 바꿉니다 .


2
... AbstractStringBuilder삽입 된 내용을위한 공간을 찾기 위해 삽입 색인을지나 모든 내용 을 이동하기 때문입니다. 그러나 이것은 구현 세부 사항이지 원칙 중 하나가 아닙니다.
entonio

1
@entonio : 사실,하지만 매우 중요한 세부 사항입니다. :)
user541686

1
나는 StringBuilder를 사용하지 말아야하는 것 같습니다. 감사합니다
user685275

@ user685275 : 예, 역방향 삽입이 필요한 경우 문자열 시작 부분에 삽입 할 수있는 것이 정말 필요합니다. 가장 쉬운 해결책은 위의 기술 (두 번 뒤집기)이라고 생각합니다. 비록 여러분이 char 배열로 더 나은 클래스를 만들 수 있지만 ( "deque"를 살펴보고 싶을 수도 있습니다).
user541686

1
@rogerdpack : 그것이 목적이 아니라 메커니즘이라고 말하고 싶습니다. 목적은 문자열 조작보다 점근 적으로 더 빠르며 잘못 사용하면 그렇지 않습니다.
user541686

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-월-IR

1
@ nom-mon-ir 그는 단지 문자열을 뒤집습니다. 왼쪽에 추가하는 방법에는 대답하지 않습니다.
Raymond Chenon 2015 년

원하는 효과를 얻습니다.
Speck

StringBuilder의 진정한 잠재력을 사용하는 처음에 삽입을 수행하는 방법을 해킹하는 대신이 방법을 사용할 수있는 경우가있을 수 있다고 생각합니다. 어쨌든 루프를 되돌릴 수없는 경우가 있으므로 다른 답변도 필요합니다.
PhoneixS

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를 전달하여 채우는 재귀 솔루션에 대해 생각할 수도 있습니다. 이렇게하면 역 처리 등을 방지 할 수 있습니다. 반복을 사용하여 반복을 설계하고 종료 조건을 신중하게 결정하면됩니다.

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

나는 전면 추가 사례에만 집중할 것입니다. case 2 및 case 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);
}

참고 : 삽입 메서드는 모든 유형의 기본 형식을 허용하므로 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) 연산을하고 있습니다.

자바 문서의 스 니펫 :

Object 인수의 문자열 표현을이 문자 시퀀스에 삽입합니다. 전체적인 효과는 마치 두 번째 인수가 메서드에 의해 문자열로 변환되고 해당 문자열 String.valueOf(Object)의 문자가 표시된 오프셋에서이 문자 시퀀스에 삽입 된 것과 똑같습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.