関連する.NETに関する質問 を参照してください。
私は["a","b","c"]
が"a,b,c"
になるようにsplitの正反対のことをする迅速で簡単な方法を探しています。
配列を繰り返し処理するには、条件を追加する(これが最後の要素ではない場合は区切り文字を追加する)か、最後の区切り文字を削除するために部分文字列を使用する必要があります。
それを行うための認定された効率的な方法があると私は確信しています(Apache Commons?)
あなたのプロジェクトでどのようにそれを好むのですか?
Java 8を使用すると、非常にきれいな方法でこれを行うことができます。
String.join(delimiter, elements);
これは3つの方法で機能します。
1)要素を直接指定する
String joined1 = String.join(",", "a", "b", "c");
2)配列を使う
String[] array = new String[] { "a", "b", "c" };
String joined2 = String.join(",", array);
3)イテラブルを使う
List<String> list = Arrays.asList(array);
String joined3 = String.join(",", list);
あなたがAndroidの上にいるならば、あなたはすることができます TextUtils.join(delimiter, tokens)
私はこの特定の問題に対して Google Collections ApacheのStringUtilsよりも好む:
Joiner.on(separator).join(array)
StringUtilsと比較して、Joiner APIは流暢なデザインを持ち、もう少し柔軟です。 null
要素はスキップするか、プレースホルダーに置き換えることができます。また、Joiner
には、キーと値の間に区切り記号を使ってマップを結合する機能があります。
Apache Commons Lang はString
配列を指定された区切り文字でつなぐ StringUtils.join
メソッドを実際に持っています。
例えば:
String[] s = new String[] {"a", "b", "c"};
String joined = StringUtils.join(s, ","); // "a,b,c"
しかし、私が思うに、あなたが言及したように、上記のメソッドの実際の実装ではある種の条件付きまたはサブストリング処理がなければならないと思います。
私がString
への参加を実行しようとしていて、他にCommons Langを使用する理由がなければ、おそらく私は自分自身を転用して外部ライブラリへの依存関係の数を減らすでしょう。
サードパーティがなくても速くて簡単な解決策が含まれています。
public static String strJoin(String[] aArr, String sSep) {
StringBuilder sbStr = new StringBuilder();
for (int i = 0, il = aArr.length; i < il; i++) {
if (i > 0)
sbStr.append(sSep);
sbStr.append(aArr[i]);
}
return sbStr.toString();
}
「それを実行するための認定された効率的な方法があると確信しています(Apache Commons?)」
はい、明らかに
StringUtils.join(array, separator)
Java 1.8には新しい StringJoinerクラス - があるので、GuavaやApache Commonsは必要ありません。
String str = new StringJoiner(",").add("a").add("b").add("c").toString();
あるいは新しいストリームapiでコレクションを直接使う:
String str = Arrays.asList("a", "b", "c").stream().collect(Collectors.joining(","));
さらに簡単にするには、単に配列を使用することができます。そのため、配列の値を "、"で区切った文字列を取得できます。
String concat = Arrays.toString(myArray);
だからあなたはこれで終わるでしょう:concat = "[a、b、c]"
アップデート
Jeffが提案しているように、サブストリングを使って大括弧を取り除くことができます。
concat = concat.substring(1, concat.length() -1);
だからあなたはconcat = "a、b、c"で終わる
ReplaceとreplaceAllは正規表現で使用できます。
String[] strings = {"a", "b", "c"};
String result = Arrays.asList(strings).toString().replaceAll("(^\\[|\\]$)", "").replace(", ", ",");
Arrays.asList().toString()
は "[a、b、c]"を生成するので、最初の括弧と最後の括弧を削除するためにreplaceAll
を実行します。その後、(オプションで) "、"のシーケンスを変更することができます。
剥ぎ取りバージョン(文字数が少ない):
String[] strings = {"a", "b", "c"};
String result = ("" + Arrays.asList(strings)).replaceAll("(^.|.$)", "").replace(", ", "," );
正規表現は非常に強力で、特にStringメソッドの "replaceFirst"と "replaceAll"です。試してみてください。
他のすべての回答にはランタイムオーバーヘッドが含まれています... ArrayList.toString()。replaceAll(...)を使用することは非常に無駄です。
オーバーヘッドがゼロの最適なアルゴリズムを紹介します。他のオプションほど見た目はよくありませんが、内部的にはこれがすべてのことです(他の隠れたチェック、複数の配列の割り当て、その他の混乱の後)。
あなたがすでにあなたが文字列を扱っていることを知っているので、あなたは手動ですべてを実行することによってたくさんの配列割り当てを節約することができます。これはきれいではありませんが、他の実装によって行われた実際のメソッド呼び出しをトレースすると、実行時のオーバーヘッドが最小限に抑えられます。
public static String join(String separator, String ... values) {
if (values.length==0)return "";//need at least one element
//all string operations use a new array, so minimize all calls possible
char[] sep = separator.toCharArray();
// determine final size and normalize nulls
int totalSize = (values.length - 1) * sep.length;// separator size
for (int i = 0; i < values.length; i++) {
if (values[i] == null)
values[i] = "";
else
totalSize += values[i].length();
}
//exact size; no bounds checks or resizes
char[] joined = new char[totalSize];
int pos = 0;
//note, we are iterating all the elements except the last one
for (int i = 0, end = values.length-1; i < end; i++) {
System.arraycopy(values[i].toCharArray(), 0,
joined, pos, values[i].length());
pos += values[i].length();
System.arraycopy(sep, 0, joined, pos, sep.length);
pos += sep.length;
}
//now, add the last element;
//this is why we checked values.length == 0 off the hop
System.arraycopy(values[values.length-1].toCharArray(), 0,
joined, pos, values[values.length-1].length());
return new String(joined);
}
このオプションは速くて明確です:
public static String join(String separator, String... values) {
StringBuilder sb = new StringBuilder(128);
int end = 0;
for (String s : values) {
if (s != null) {
sb.append(s);
end = sb.length();
sb.append(separator);
}
}
return sb.substring(0, end);
}
この小さな機能は常に役に立ちます。
public static String join(String[] strings, int startIndex, String separator) {
StringBuffer sb = new StringBuffer();
for (int i=startIndex; i < strings.length; i++) {
if (i != startIndex) sb.append(separator);
sb.append(strings[i]);
}
return sb.toString();
}
私がとったアプローチは、読みやすさを提供し、古いJavaバージョンとの後方互換性のための合理的なオプションを維持するためにJava 1.0から発展しました。一方、Apache commons-langからのドロップイン置き換えのメソッドシグネチャも提供します。パフォーマンス上の理由から、Arrays.asListの使用に反対する可能性がいくつかありますが、実際の作業を実行する1つのメソッドを複製することなく、適切なデフォルト値を持つヘルパーメソッドをお勧めします。このアプローチは、呼び出す前に配列/リスト変換を必要としない信頼性の高いメソッドへの適切なエントリポイントを提供します。
Javaバージョンの互換性について考えられるバリエーションには、StringBuilder(Java 1.5)の代わりにStringBuffer(Java 1.0)を使用すること、Java 1.5イテレーターを切り替えること、およびコレクションから汎用ワイルドカード(Java 1.5)を削除すること(Java 1.2)があります。下位互換性をさらに一段階上げるには、Collectionを使用しているメソッドを削除し、ロジックを配列ベースのメソッドに移動します。
public static String join(String[] values)
{
return join(values, ',');
}
public static String join(String[] values, char delimiter)
{
return join(Arrays.asList(values), String.valueOf(delimiter));
}
// To match Apache commons-lang: StringUtils.join(values, delimiter)
public static String join(String[] values, String delimiter)
{
return join(Arrays.asList(values), delimiter);
}
public static String join(Collection<?> values)
{
return join(values, ',');
}
public static String join(Collection<?> values, char delimiter)
{
return join(values, String.valueOf(delimiter));
}
public static String join(Collection<?> values, String delimiter)
{
if (values == null)
{
return new String();
}
StringBuffer strbuf = new StringBuffer();
boolean first = true;
for (Object value : values)
{
if (!first) { strbuf.append(delimiter); } else { first = false; }
strbuf.append(value.toString());
}
return strbuf.toString();
}
public String join(String[] str, String separator){
String retval = "";
for (String s: str){ retval+= separator + s;}
return retval.replaceFirst(separator, "");
}