n 개의 문자로 문자열 만들기


144

Java에서 지정된 수의 지정된 문자로 문자열을 만드는 방법이 있습니까? 필자의 경우 공백이 10 개인 문자열을 만들어야합니다. 내 현재 코드는 다음과 같습니다

StringBuffer outputBuffer = new StringBuffer(length);
for (int i = 0; i < length; i++){
   outputBuffer.append(" ");
}
return outputBuffer.toString();

같은 것을 성취하는 더 좋은 방법이 있습니까? 특히 나는 (실행 측면에서) 빠른 것을 원합니다.


1
자신이 많은 일을하는 것을 발견하면 다음과 같은 함수를 작성하십시오. 그런 다음 필요할 때 전화하십시오.
— 오스틴 피츠 패트릭

12
StringBuffer 대신 StringBuilder를 사용하려고합니다

버퍼의 크기를 시작하면서 추가 할 수 있으며, 메모리 관리가 용이 ​​해집니다!. StringBuilder outputBuffer = 새로운 StringBuilder (repeat * base.length ());
— Victor


단일 공간을 추가하려면 append(' ')대신 사용하십시오. 컴퓨팅이 조금 덜 필요합니다.
— Erk

답변:


36

for 루프는 컴파일러에 의해 최적화됩니다. 당신과 같은 경우에는 스스로 최적화 할 필요가 없습니다. 컴파일러를 신뢰하십시오.

BTW, n 개의 공백 문자로 문자열을 만드는 방법이 있다면 방금했던 것과 같은 방식으로 코딩됩니다.


1
이것이 최적화되지 않았더라도-프로그램에서 얼마나 자주 생성되는지-정적 변수 또는 다른 캐시에 저장되는 경우
— mmmmmm

btw Array.fill ()은 배열을 반복합니다. / me 다른 게시물에 댓글을 달려면 확실히 더 많은 포인트가 필요합니다 :)
— kalkin

@Mark Length는 가변적이므로 저장하는 것이 어리석은 것 같습니다. 내가 무엇을해야 static Dictionary<int, String>합니까?
— C. Ross

1
문자열을 원할 때 가장 길게 저장 한 후 다음과 같이 사용하십시오. " ".substring(0, 10);
— mjaggard

169

StringAPI를 사용하는 가장 짧은 코드는 다음과 같습니다.

String space10 = new String(new char[10]).replace('\0', ' ');

System.out.println("[" + space10 + "]");
// prints "[          ]"

직접 인스턴스화하지 않고 방법으로 char:

import java.nio.CharBuffer;

/**
 * Creates a string of spaces that is 'spaces' spaces long.
 *
 * @param spaces The number of spaces to add to the string.
 */
public String spaces( int spaces ) {
  return CharBuffer.allocate( spaces ).toString().replace( '\0', ' ' );
}

다음을 사용하여 호출하십시오.

System.out.printf( "[%s]%n", spaces( 10 ) );

4
하나의 라이너를 좋아하지만 FrustratedWithFormsDes의 솔루션은 \ 0에 대해 각각을 검사하지 않고 단순히 공간을 할당하기 때문에 실행과 관련하여 더 낫습니다.
— Bouncner

1
테스트 한 결과 루프보다 항상 빠르며 50000-100000 나노 초 더 빠릅니다. 총 시간이 여전히 높지만 반복 횟수가 증가함에 따라 루프가 훨씬 빨라질 수 있습니다 (0.1 밀리 초). 다른 크기의 공간 문자열을 만들 때도 마찬가지입니다.
— kmecpp

꽤 좋은 솔루션을 쿵, 여기 내 대답에 그것을 사용했다 stackoverflow.com/questions/852665/...
— maytham-ɯɐɥʇʎɐɯ

66

흠 이제 내가 생각할 것입니다 Arrays.fill.

char[] charArray = new char[length];
Arrays.fill(charArray, ' ');
String str = new String(charArray);

물론, fill메소드가 코드와 동일한 작업을 수행 한다고 가정 하므로 아마도 거의 동일하게 수행되지만 최소한 줄 수는 적습니다.


2
소스를 확인한 후에는 실제로 OP가 게시 한 내용과 정확히 일치하는 것 같습니다. docjar.com/html/api/java/util/Arrays.java.html의
— Pops

2
@Lord Torgamus OP의 질문이 편집 되었습니까? 내가 본 버전에서, 그는 StringBuffer.append ()에서 루핑하고 있으며, Frustrated의 버전은 채우기를 수행하고 있습니다 (물론 배열에 대한 문자 할당을 반복합니다). 전혀 같은 것이 아닙니다.
— CPerkins

@ CPerkins, 충분히 공정한, 나는 명확하지 않았다. 내 요점은 둘 다 for 루프 내에서 문자별로 삽입하는 것입니다.
— Pops

1
@로드 Torgamus-그것에 동의했다. 유감스럽게도 jvm은 memset을 수행 할 수 없습니다. 넓은 문자에 대해 지불하는 가격입니다.
— CPerkins

2
@Pops Arrays.fill()코드 와 (표준 및 외부) 라이브러리 코드 에서이 작업을 수행하기 위해 함수가 일관되게 사용 되면 핫스팟 컴파일의 좋은 후보가되고 CPU 캐시를 찾을 가능성이 높아집니다. 향후 JVM은이를 고유 함수 로 지정할 수 있습니다. 자신을
— 굴리면

65

나는 루프를 손으로 쓰지 말 것을 강력히 권합니다. 당신은 프로그래밍 경력 동안 반복해서 그렇게 할 것입니다. 코드를 읽는 사람들은-당신을 포함하여-루프의 의미를 소화하기 위해 몇 초 만에 시간을 투자해야합니다.

대신 재사용 만 수행하는 코드를 제공하는 사용 가능한 라이브러리 중 하나 같은 StringUtils.repeat에서 아파치 코 몬즈 랭 :

StringUtils.repeat(' ', length);

그렇게하면 성능에 신경 쓰지 않아도되므로 StringBuilder컴파일러 최적화 등 의 모든 세부 사항 이 숨겨집니다. 함수가 느리게 나오면 라이브러리의 버그 일 것입니다.

로 자바 (11) 가 더 쉽게된다 :

" ".repeat(length);

5
반면에 StringUtils가 프로젝트에서 아직 사용되지 않은 경우 이러한 간단한 작업에 대한 또 다른 종속성을 추가하는 것은 과도한 작업 일 수 있습니다.
— Erich Kitzmueller

1
속도가 느리면 기능에 대한 수정 사항을 제출할 수도 있습니다.
— 됩니다


13

공백 만 원하면 어떻습니까?

String spaces = (n==0)?"":String.format("%"+n+"s", "");

abs (n) 공백이 발생합니다.


6
속도는 어떻습니까? 노출 형식이 비교적 느립니다. 결국 문자열을 구문 분석해야합니다.
— C. Ross

11

Java 11 이후 :

" ".repeat(10);

Java 8 부터 :

generate(() -> " ").limit(10).collect(joining());

어디:

import static java.util.stream.Collectors.joining;
import static java.util.stream.Stream.generate;

9

Java 11부터는 간단히 String.repeat(count)문제를 해결하는 데 사용할 수 있습니다.

이 문자열을 반복해서 연결 한 값을 가진 문자열을 반환합니다 count.

이 문자열이 비어 있거나 count0이면 빈 문자열이 반환됩니다.

따라서 루프 대신 코드는 다음과 같습니다.

" ".repeat(length);

8

나는 이것이 가능한 코드가 아니라고 생각하고 Guava Joiner 클래스를 사용합니다.

결합 자 .on ( ""). join ( Collections.nCopies (10, ""));


가장 짧은 코드 줄이지 만 간단한 작업을 위해 큰 라이브러리를 추가하는 것은 의미가 없습니다. pubic String n(int n) { ... }"더 적은"코드를 허용 하는 단일 메소드 를 사용하여 더 작은 JAR을 직접 작성할 수 있습니다 . n(10)그러나 다시 말이되지 않습니다.
— isapir

@isapir 이것은 이미 구아바를 사용하는 사람들에게 훌륭한 답변입니다
— nasch

1
@nasch Guava는 질문의 일부가 아닙니다. 그러나 어쨌든 2018 년에 Java 8에 추가 된 String.join ()을 사용할 수있을 때 Guava의 Joiner를 사용할 이유가 실제로 없습니다. stackoverflow.com/a/43011939/968244
— isapir

@isapir 아니요, 구아바가 답이었습니다. StackOverflow에 대한 답변은 질문을하는 사람보다 더 많은 청중을 갖습니다. 따라서 일부 답변이 요청하는 사람에게 적합하지 않은 경우에 좋습니다. 그리고 String.join ()에 대한 의견은 훌륭한 버전이지만 모든 Android 버전에서 사용할 수 있는지 잘 모르겠습니다. 이는 Java를 많이 사용합니다.
— nasch

7

String.formatN 개의 공간을 생성 하기 위해 표준 기능을 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

String.format("%5c", ' ');

공백이 5 개인 문자열을 만듭니다.

또는

int count = 15;
String fifteenSpacebars = String.format("%" + count + "c", ' ');

15 개의 스페이스 바 문자열을 만듭니다.

다른 기호를 반복하려면 공백을 원하는 기호로 바꿔야합니다.

int count = 7;
char mySymbol = '#';
System.out.println(String.format("%" + count + "c", ' ').replaceAll("\\ ", "\\" + mySymbol));

산출:

#######

6

빠른 지수화 알고리즘을 기반으로 한 나의 기여.

/**
 * Repeats the given {@link String} n times.
 * 
 * @param str
 *            the {@link String} to repeat.
 * @param n
 *            the repetition count.
 * @throws IllegalArgumentException
 *             when the given repetition count is smaller than zero.
 * @return the given {@link String} repeated n times.
 */
public static String repeat(String str, int n) {
    if (n < 0)
        throw new IllegalArgumentException(
                "the given repetition count is smaller than zero!");
    else if (n == 0)
        return "";
    else if (n == 1)
        return str;
    else if (n % 2 == 0) {
        String s = repeat(str, n / 2);
        return s.concat(s);
    } else
        return str.concat(repeat(str, n - 1));
}

다른 두 가지 접근 방식에 대해 알고리즘을 테스트했습니다.

  • String.concat()문자열을 연결 하는 데 사용 되는 정규 for 루프
  • a를 사용하여 규칙적인 for 루프 StringBuilder

테스트 코드 (for 루프를 사용하여 연결 String.concat()하고 크게 느리게 n되므로 5 번째 반복 후에 생략했습니다).

/**
 * Test the string concatenation operation.
 * 
 * @param args
 */
public static void main(String[] args) {
    long startTime;
    String str = " ";

    int n = 1;
    for (int j = 0; j < 9; ++j) {
        n *= 10;
        System.out.format("Performing test with n=%d\n", n);

        startTime = System.currentTimeMillis();
        StringUtil.repeat(str, n);
        System.out
                .format("\tStringUtil.repeat() concatenation performed in    %d milliseconds\n",
                        System.currentTimeMillis() - startTime);

        if (j <5) {
            startTime = System.currentTimeMillis();
            String string = "";
            for (int i = 0; i < n; ++i)
                string = string.concat(str);
            System.out
                    .format("\tString.concat() concatenation performed in        %d milliseconds\n",
                            System.currentTimeMillis() - startTime);
        } else
            System.out
                    .format("\tString.concat() concatenation performed in        x milliseconds\n");
        startTime = System.currentTimeMillis();
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < n; ++i)
            b.append(str);
        b.toString();
        System.out
                .format("\tStringBuilder.append() concatenation performed in %d milliseconds\n",
                        System.currentTimeMillis() - startTime);
    }
}

결과 :

Performing test with n=10
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        0 milliseconds
    StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=100
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1 milliseconds
    StringBuilder.append() concatenation performed in 0 milliseconds
Performing test with n=1000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1 milliseconds
    StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=10000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        43 milliseconds
    StringBuilder.append() concatenation performed in 5 milliseconds
Performing test with n=100000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        1579 milliseconds
    StringBuilder.append() concatenation performed in 1 milliseconds
Performing test with n=1000000
    StringUtil.repeat() concatenation performed in    0 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 10 milliseconds
Performing test with n=10000000
    StringUtil.repeat() concatenation performed in    7 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 112 milliseconds
Performing test with n=100000000
    StringUtil.repeat() concatenation performed in    80 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 1107 milliseconds
Performing test with n=1000000000
    StringUtil.repeat() concatenation performed in    1372 milliseconds
    String.concat() concatenation performed in        x milliseconds
    StringBuilder.append() concatenation performed in 12125 milliseconds

결론:

  • 큰 경우 n-재귀 접근법을 사용하십시오.
  • 작은 nfor 루프의 속도는 충분합니다

4
이것은 흥미로운 구현입니다. 불행히도, 당신의 결론과 달리, 그것은 큰 n에 대해 매우 비효율적입니다. 나는 이것이 문자열을 연결할 때마다 진행되는 많은 메모리 할당 때문이라고 생각합니다. String 대신 StringBuilder를 사용하는 재귀 메서드 주위에 래퍼로 ​​작성하십시오. 결과가 훨씬 나아질 것입니다.
— Klitos Kyriacou

3
이와 같은 마이크로 벤치마킹을 할 때주의해야 할 사항이 많이 있습니다. 이 코드의 주된 성능 문제는 핫스팟으로 컴파일되었는지, 얼마나 많은 가비지를 생성하는지 등입니다. 모든 if문장이 CPU의 분기 예측을 망칠 것이라고 확신합니다 . JMH ( openjdk.java.net/projects/code-tools/jmh )를 사용하여 실제로 다시 작성해야합니다 . 그렇지 않으면 조금 의미가 없습니다.
— SusanW

이 구현은 O (n * log n) 복잡성을 가지지 만 StringBuilder는 O (n) :)
— Leo Leontev


4

우리는 다음을 고려합니다.

String c = "c"; // character to repeat, for empty it would be " ";
int n = 4; // number of times to repeat
String EMPTY_STRING = ""; // empty string (can be put in utility class)

Java 8 (스트림 사용)

String resultOne = IntStream.range(0,n)
   .mapToObj(i->c).collect(Collectors.joining(EMPTY_STRING)); // cccc

Java 8 (nCopies 사용)

String resultTwo = String.join(EMPTY_STRING, Collections.nCopies(n, c)); //cccc

1
Collectors.joining(EMPTY_STRING)에 해당합니다Collectors.joining()
— PPartisan

2

RandomStringUtils 에는 주어진 입력 크기에서 문자열을 작성하는 규정이 있습니다. 캔 트는 속도에 대해 언급하지만 하나의 라이너입니다.

RandomStringUtils.random(5,"\t");

출력을 만듭니다

\ t \ t \ t \ t \ t

코드에서 \ 0 을보고 싶지 않으면 선호됩니다 .



1

대부분의 경우 문자열은 특정 길이까지만 필요합니다 (예 : 100 칸). 인덱스 번호가 공백으로 채워진 문자열의 크기와 같은 문자열 배열을 준비하고 필요한 길이가 한계 내에 있거나 문자열이 경계를 벗어나면 필요에 따라 문자열을 조회 할 수 있습니다.



0

그냥 당신의 StringBuffer를 교체 하여 StringBuilder . 그것을 이길 어렵다.

길이가 큰 숫자 인 경우 각 반복에서 길이를 복제하여 좀 더 효율적인 (하지만 더 서투른) 자체 추가를 구현할 수 있습니다.

 public static String dummyString(char c, int len) {
  if( len < 1 ) return "";
  StringBuilder sb = new StringBuilder(len).append(c);
  int remnant = len - sb.length();
  while(remnant  > 0) {
   if( remnant  >= sb.length() ) sb.append(sb);
   else sb.append(sb.subSequence(0, remnant));
   remnant  = len - sb.length();
  }
  return sb.toString();
 }

또한 Arrays.fill()aproach ( FrustratedWithFormsDesigner 의 답변)를 시도 할 수 있습니다 .


변수의 이름을 둘 이상의 문자로 지정할 수 있습니까?
— C. Ross

0

당신은 대체 할 수 StringBuffer와 StringBuilder(후자가 동기화되지, 더 빠른 단일 스레드 응용 프로그램에서 할 수있다)

또한 StringBuilder필요할 때마다 인스턴스를 생성하는 대신 인스턴스를 한 번 생성 할 수 있습니다 .

이 같은:

class BuildString {
     private final StringBuilder builder = new StringBuilder();
     public String stringOf( char c , int times ) {

         for( int i = 0 ; i < times ; i++  ) {
             builder.append( c );
         }
         String result = builder.toString();
         builder.delete( 0 , builder.length() -1 );
         return result;
      }

  }

그리고 이것을 다음과 같이 사용하십시오 :

 BuildString createA = new BuildString();
 String empty = createA.stringOf( ' ', 10 );

createA인스턴스 변수로 보유 하는 경우 인스턴스 작성 시간을 절약 할 수 있습니다.

스레드가 안전하지 않습니다. 다중 스레드가있는 경우 각 스레드마다 고유 한 사본이 있어야합니다.


0

좋은 성능을 위해 aznilamir 와 FrustratedWithFormsDesigner의 답변을 결합하십시오.

private static final String BLANKS = "                       ";
private static String getBlankLine( int length )
{
    if( length <= BLANKS.length() )
    {
        return BLANKS.substring( 0, length );
    }
    else
    {
        char[] array = new char[ length ];
        Arrays.fill( array, ' ' );
        return new String( array );
    }
}

BLANKS요구 사항 에 따라 크기를 조정 하십시오. 내 특정 BLANKS문자열의 길이는 약 200 자입니다.


0

이와 같은 방법을 사용하십시오. 이것은 String주어진 String길이의 끝에 특정 길이의 길이 를 만들기 위해 주어진 끝에 필요한 공간을 추가합니다 .

public static String fillSpaces (String str) {

    // the spaces string should contain spaces exceeding the max needed
    String spaces = "                                                   ";
    return str + spaces.substring(str.length());
}

0

데이터 크기를 조정하기 위해 문자열 크기를 고정 시키려면 패딩 또는 자르기를 원합니다 ...

class Playground {
    private static String fixStrSize(String s, int n) {
        return String.format("%-" + n + "s", String.format("%." + n +"s", s));
    }

    public static void main(String[ ] args) {
        System.out.println("|"+fixStrSize("Hell",8)+"|");
        System.out.println("|"+fixStrSize("Hells Bells Java Smells",8)+"|");
    }
}

|Hell    |
|Hells Be|

여기에 훌륭한 참조 .


0

이것은 Java 8에서 외부 라이브러리를 사용하지 않고 나를 위해 해결되었습니다.

String sampleText = "test"
int n = 3;
String output = String.join("", Collections.nCopies(n, sampleText));
System.out.println(output);

그리고 출력은

testtesttest

0

int c = 10; 문자열 공간 = String.format ( "%"+ c + "c", ''); 이렇게하면 문제가 해결됩니다.


-1

아래와 같은 간단한 방법도 사용할 수 있습니다

public static String padString(String str, int leng,char chr) {
        for (int i = str.length(); i <= leng; i++)
            str += chr;
        return str;
    }

이것은 상당히 느립니다.
— SLaks

처리하는 문자열의 크기가 큰 경우 문자열 연결 대신 StringBuffer를 사용할 수 있습니다. 그것은 속도에 상당한 영향을 미칠 것입니다
— Yashpal Singla

-2

이건 어때요?

public String fillSpaces(int len) {
    /* the spaces string should contain spaces exceeding the max needed */  
    String spaces = "                                                   ";
    return spaces.substring(0,len);
}

편집 : 나는 개념과 여기에서 내가 찾은 것을 테스트하기 위해 간단한 코드를 작성했습니다.

방법 1 : 루프에서 단일 공간 추가

  public String execLoopSingleSpace(int len){
    StringBuilder sb = new StringBuilder();

    for(int i=0; i < len; i++) {
        sb.append(' ');
    }

    return sb.toString();
  }

방법 2 : 100 개의 공백을 추가하고 반복 한 다음 하위 문자열 :

  public String execLoopHundredSpaces(int len){
    StringBuilder sb = new StringBuilder("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ");

    for (int i=0; i < len/100 ; i++) {
        sb.append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ")
            .append("          ").append("          ").append("          ");
    }

    return sb.toString().substring(0,len);
  }

결과는 12,345,678 개의 공백을 만듭니다.

C:\docs\Projects> java FillSpace 12345678
method 1: append single spaces for 12345678 times. Time taken is **234ms**. Length of String is 12345678
method 2: append 100 spaces for 123456 times. Time taken is **141ms**. Length of String is 12345678
Process java exited with code 0

10,000,000 개의 공간에서 :

C:\docs\Projects> java FillSpace 10000000
method 1: append single spaces for 10000000 times. Time taken is **157ms**. Length of String is 10000000
method 2: append 100 spaces for 100000 times. Time taken is **109ms**. Length of String is 10000000
Process java exited with code 0

직접 할당과 반복을 결합하면 큰 공간을 만들 때 항상 평균 60ms 더 적은 시간이 걸립니다. 작은 크기의 경우 두 결과 모두 무시할 수 있습니다.

그러나 의견을 계속하십시오 :-)


3
@ aznilamir : 흠, 당신은 어떻게 10k 공간을 위해 할 것입니까?
— Jayan

아이디어는 100 개의 공간을 루프와 직접 할당하는 것입니다. 다음은 코드 스 니펫입니다.
— aznilamir

여러 개의 추가 기능을 사용하여 100자를 추가하는 이유는 무엇입니까? 왜 100 개의 문자가 추가되지 않습니까?
— nycynik

-3

나는 당신이 요구하는 것에 대한 내장 방법이 없다는 것을 알고 있습니다. 그러나 10과 같은 작은 고정 길이의 경우 방법이 훨씬 빠릅니다.


만약 그것이 10과 같은 작은 고정 길이라면
— C. Ross
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.