Javaに、指定した文字の指定した数の文字列を作成する方法はありますか?私の場合、10個のスペースを含む文字列を作成する必要があります。私の現在のコードは:
StringBuffer outputBuffer = new StringBuffer(length);
for (int i = 0; i < length; i++){
outputBuffer.append(" ");
}
return outputBuffer.toString();
同じことを達成するためのより良い方法はありますか。特に、(実行に関して)高速なものが欲しいです。
Forループはコンパイラーによって最適化されます。あなたのようなそのような場合、あなた自身で最適化を気にする必要はありません。コンパイラを信頼します。 :)
編集:ところで、n個のスペース文字を含む文字列を作成する方法がある場合は、ちょうどあなたがやったのと同じ方法でコーディングされています。
おそらくString
APIを使用した最短のコード。
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 ) );
うーん、私はそれについて考えているので、多分 Arrays.fill
:
char[] charArray = new char[length];
Arrays.fill(charArray, ' ');
String str = new String(charArray);
もちろん、fill
メソッドはコードと同じことを行うため、おそらくほぼ同じパフォーマンスを発揮しますが、少なくともこれは少ない行です。
ループを手書きで書かないことを強くお勧めします。あなたはあなたのプログラミングのキャリアの中で何度もそれを繰り返します。あなたを含むあなたのコードを読んでいる人々は、たとえほんの数秒であっても、ループの意味を消化するために常に時間を費やさなければなりません。
代わりにreuseStringUtils.repeat
fromのようなコードを提供する利用可能なライブラリの1つ Apache Commons Lang :
StringUtils.repeat(' ', length);
そうすれば、パフォーマンスを気にする必要もありません。したがって、StringBuilder
やコンパイラの最適化などの詳細はすべて隠されます。関数が遅いと判明した場合、ライブラリのバグになります。
Java 11 を使用すると、さらに簡単になります。
" ".repeat(length);
Java 8では、String.join
を使用できます。
String.join("", Collections.nCopies(n, s));
スペースのみが必要な場合は、次のようにします。
String spaces = (n==0)?"":String.format("%"+n+"s", "");
その結果、abs(n)スペースが発生します。
私はこれが可能な限り少ないコードだと思う、それはグアバジョイナークラスを使用します:
Joiner 。on( "")。join( Collections.nCopies (10、 ""));
高速累乗のためのアルゴリズムに基づく私の貢献。
/**
* 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ループStringBuilder
を使用した通常のforループテストコード(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
の場合-再帰的アプローチを使用しますn
-forループには十分な速度がありますN個のスペースを生成するには、標準のString.format
関数を使用できます。例えば:
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));
出力:
#######
私たちが持っていることを考える:
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)
String resultOne = IntStream.range(0,n)
.mapToObj(i->c).collect(Collectors.joining(EMPTY_STRING)); // cccc
String resultTwo = String.join(EMPTY_STRING, Collections.nCopies(n, c)); //cccc
これはどう?
char[] bytes = new char[length];
Arrays.fill(bytes, ' ');
String str = new String(bytes);
StringUtilsを使用:StringUtils.repeat( ''、10)
RandomStringUtils には、指定された入力サイズから文字列を作成する機能があります。カントは速度についてコメントしますが、それはライナーです。
RandomStringUtils.random(5,"\t");
出力を作成します
\ t\t\t\t\t
コードで\ 0を見たくない場合に望ましい。
Java 11以降では、単に String.repeat(count)
を使用して問題を解決できます。
値が
count
回繰り返されたこの文字列の連結である文字列を返します。この文字列が空または
count
がゼロの場合、空の文字列が返されます。
したがって、ループの代わりに、コードは次のようになります。
" ".repeat(length);
ほとんどの場合、特定の長さ、たとえば100スペースまでの文字列のみが必要です。必要な長さが制限内であれば、インデックス番号がスペースで埋められた文字列のサイズに等しい文字列の配列を準備し、文字列を検索するか、境界外にある場合はオンデマンドで作成できます。
StringBuffer
をStringBuilder
に置き換えることができます(後者は同期されません。シングルスレッドアプリではより高速になる場合があります)
また、必要なたびに作成する代わりに、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
をインスタンス変数として保持すると、インスタンスの作成にかかる時間を節約できます。
これはスレッドセーフではありません。マルチスレッドを使用している場合、各スレッドには独自のコピーが必要です。
良好なパフォーマンスを得るには、 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文字の長さです。
Stream.generate(() -> ch).limit(n).collect(joining());
どこ:
import static Java.util.stream.Collectors.joining;
import Java.util.stream.Stream;
...
String ch = " ";
int n = 10;
Stream
.generate(() -> ch)
.limit(n)
.collect(joining());
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の答え)を試すこともできます。
このような方法があります。これにより、特定の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());
}