n文字の文字列を作成する


144

指定された数の指定された文字で文字列を作成する方法はありますか?私の場合、10スペースの文字列を作成する必要があります。私の現在のコードは:

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

同じことを達成するためのより良い方法はありますか?特に、(実行に関して)高速なものが欲しいです。


1
あなたがそれをたくさんしていることに気づいたら、関数を書くだけです:String characterRepeat(Char c、int Length){...}これは、あらゆる文字とあらゆる長さに対してあなたがそこで行うことを行います。その後、必要なときに呼び出してください。
オースティンフィッツパトリック

12
StringBufferの代わりにStringBuilderを使用したい

最初にバッファのサイズを追加すると、計算が容易になり、メモリ管理が容易になります。StringBuilder outputBuffer = new StringBuilder(repeat * base.length());
ビクター


単一のスペースを追加したい場合append(' ')は、代わりに使用してください...少し計算が少なくなります...
Erk

回答:


36

forループはコンパイラーによって最適化されます。このような場合、自分で最適化について気にする必要はありません。コンパイラを信頼します。

ところで、n個のスペース文字を含む文字列を作成する方法がある場合は、以前と同じようにコーディングします。


1
これが最適化されていない場合でも、プログラムで作成される頻度-静的変数または他のキャッシュに保存される場合が多い
mmmmmm

btw Array.fill()は、配列をループします。/ me他の投稿にコメントするには、
間違いなく

@Markの長さは可変なので、保存するのはばかげているようです。私は何をしstatic Dictionary<int, String>ますか?
C.ロス

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 2013年

1
テストすると、これは常にループよりも高速で、一貫して50000〜100000ナノ秒高速です。これは、合計時間がまだ長くても、反復回数が増えるにつれてループがかなり高速になる可能性があります(0.1ミリ秒)。これは、異なるサイズのスペース文字列を作成する場合にも当てはまります。
kmecpp 2015

かなりいいソリューション用に強打、私はここに私の答えでそれを使用しているstackoverflow.com/questions/852665/...
maytham-ɯɐɥʇʎɐɯ

66

うーん、今考えてみると、たぶんArrays.fill

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

もちろん、私はfillメソッドがコードと同じことをすることを想定しているので、ほぼ同じように実行されますが、少なくともこれは行数が少なくなります。


2
ソースをチェックした後、これは実際にはOPが投稿したとおりに動作するようです:行806 docjar.com/html/api/java/util/Arrays.java.htmlの
Pops

2
@Lord Torgamus OPの質問は編集されましたか?私が見ているバージョンでは、彼はStringBuffer.append()でループしていて、Frustratedのバージョンは塗りつぶしをしています(もちろん、配列へのchar割り当てをループします)。まったく同じではありません。
CPerkins

@CPerkins、かなり公平だ、私ははっきりしていなかった。私のポイントは、どちらもforループ内で1文字ずつ挿入することです。
ポップス

1
@Lord Torgamus-同意する。残念なことに、JVMはmemsetを実行できません。ワイドキャラクターに支払う価格。
CPerkins、

2
@Pops Arrays.fill()関数は、コード(標準および外部)ライブラリコード全体でこのジョブを実行するために一貫して使用されている場合、ホットスポットコンパイルの候補となり、CPUキャッシュが見つかる可能性が高くなります。将来のJVMはそれを組み込み関数として割り当てる可能性があります。自分で
転がすと

65

ループを手動で記述しないことを強くお勧めします。あなたはプログラミングのキャリアの中で何度もそれを繰り返します。あなたを含むあなたのコードを読む人々-たとえそれがほんの数秒であっても、ループの意味を消化するために常に時間を費やす必要があります。

代わりに、Apache Commons Langのようにそれを行うコードを提供する利用可能なライブラリの1つを再利用します。StringUtils.repeat

StringUtils.repeat(' ', length);

そうすれば、パフォーマンスについて気にする必要がないため、、StringBuilderコンパイラーの最適化などのすべての悲惨な詳細が隠されます。関数が遅くなる場合は、ライブラリのバグです。

Javaの11それがさらに容易になり:

" ".repeat(length);

5
一方、StringUtilsがプロジェクトでまだ使用されていない場合、そのような単純なタスクにさらに別の依存関係を追加するのはやり過ぎかもしれません。
Erich Kitzmueller

1
それが遅いことが判明した場合は、関数の独自の修正を送信することもできます。


13

スペースのみが必要な場合は、次のようにします。

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

これにより、abs(n)スペースが生成されます。


6
スピードはどうですか?表示形式が比較的遅いのですが。結局それを作成する前に、文字列を解析する必要があります。
C.ロス

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

この文字列が空またはcountゼロの場合、空の文字列が返されます。

したがって、ループの代わりに、コードは次のようになります。

" ".repeat(length);

8

私はこれが可能なコードが少ないと思います、それはGuava Joinerクラスを使用します:

ジョイナー .on( "")。join(Collections.nCopies(10、 ""));


コードの最短の行ですが、その単純なタスクのためだけに大きなライブラリを追加することは意味がありません。pubic String n(int n) { ... }「より少ない」コードでも使用できる単一のメソッドを使用して、自分で小さなJARを作成できますが、これn(10)も意味がありません。
isapir 2018年

@isapirこれは、すでにグアバを使用している人にとって素晴らしい回答です
nasch

1
@nasch Guavaは質問の一部ではありませんでした。しかし、いずれにせよ、2018年には、Java 8を参照するに追加されましたString.join()を使用することができたときにグアバのジョイナーを使用する理由は本当にありませんstackoverflow.com/a/43011939/968244
isapir

@isapirいいえ、グアバは答えでした。StackOverflowでの回答は、質問をする人よりも聴衆が多いので、一部の回答が質問する人にとって最良ではない場合でも問題ありません。そして、String.join()に関するコメントは素晴らしいものですが、Javaの顕著な使用であるAndroidのすべてのバージョンで利用できるかどうかはわかりません。
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));
}

他の2つのアプローチに対してアルゴリズムをテストしました。

  • String.concat()文字列を連結するために使用する通常のforループ
  • を使用した通常のforループ StringBuilder

テストコード(forループを使用した連結でString.concat()、largeの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-再帰的アプローチを使用する
  • 小さいn場合-forループは十分な速度があります

4
これは興味深い実装です。残念ながら、あなたの結論に反して、それは大きなnに対しては非常に非効率的です。これは、文字列を連結するたびに多くのメモリ割り当てが行われているためだと思います。StringではなくStringBuilderを使用する再帰メソッドのラッパーとして記述してみてください。きっと結果ははるかに良くなるでしょう。
クリトスキリアク

3
このようなものをマイクロベンチマークするとき、あなたがしなければならない多くの予防策があり、あなたはそれらのどれもとっていないと思います!このコードに関するパフォーマンスに関する主な問題は、ホットスポットでコンパイルされているかどうか、作成されたガベージの量などです。これらのifステートメントはすべて、CPUの分岐予測を台無しにするでしょう。これは実際にはJMH(openjdk.java.net/projects/code-tools/jmh)を使用してやり直す必要があります。それ以外の場合は少し無意味です。
SusanW 2016

この実装には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()アプローチを試すかもしれません(FrustratedWithFormsDesignerの答え)。


一部の変数に複数の文字を指定できますか?
C.ロス

0

あなたは置き換えることができStringBufferStringBuilder(後者は同期されていない、より高速なシングルスレッドのアプリケーションであってもよいです)

またStringBuilder、必要になるたびにインスタンスを作成する代わりに、インスタンスを1回作成することもできます。

このようなもの:

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

優れたパフォーマンスを得るには、aznilamirFrustratedWithFormsDesignerの回答を組み合わせます

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 2013年

扱う文字列のサイズが大きい場合は、文字列連結の代わりに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

直接割り当てと反復を組み合わせると、常に時間がかかりません。巨大なスペースを作成する場合、平均で60ミリ秒かかります。サイズが小さい場合、両方の結果は無視できます。

しかし、コメントを続けてください:-)


3
@ aznilamir:うーん、あなたは10000スペースのためにどうしますか?
Jayan

アイデアは、ループと100スペースの直接割り当てを組み合わせることです。ここでは、コードスニペットです:
aznilamir

複数の追加を使用して100文字を追加するのはなぜですか?なぜ100文字追加しないのですか?
nycynik 2016

-3

私はあなたが尋ねているもののための組み込みの方法を知りません。ただし、10のような小さな固定長の場合、メソッドはかなり高速になるはずです。


それが10のような小さな固定長だったとしたら
C.ロス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.