文字列の配列を区切られた文字列に結合する方法を探しています。split() の反対です。
自分で書いてみる前にフォーラムに質問したかった(JDKにはすべてがあるため)
私が認識しているJDKには、これに対するメソッドはありません。Apache Commons Langには、必要な処理を実行するさまざまなオーバーロードjoin()
メソッドがStringUtils
クラスに含まれています。
この機能は、Arrays
ユーティリティ パッケージからこっそり取り出すことができます。
import java.util.Arrays;
...
String delim = ":",
csv_record = "Field0:Field1:Field2",
fields[] = csv_record.split(delim);
String rebuilt_record = Arrays.toString(fields)
.replace(", ", delim)
.replaceAll("[\\[\\]]", "");
ここで次の例を取得しました
/*
7) Join Strings using separator >>>AB$#$CD$#$EF
*/
import org.apache.commons.lang.StringUtils;
public class StringUtilsTrial {
public static void main(String[] args) {
// Join all Strings in the Array into a Single String, separated by $#$
System.out.println("7) Join Strings using separator >>>"
+ StringUtils.join(new String[] { "AB", "CD", "EF" }, "$#$"));
}
}
コレクションで動作する独自のロールを作成したい場合は、 DZone スニペットにいくつかの例があります。例えば:
public static String join(AbstractCollection<String> s, String delimiter) {
if (s == null || s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuilder builder = new StringBuilder(iter.next());
while( iter.hasNext() )
{
builder.append(delimiter).append(iter.next());
}
return builder.toString();
}
以前のすべての回答に基づいて:
public static String join(Iterable<? extends Object> elements, CharSequence separator)
{
StringBuilder builder = new StringBuilder();
if (elements != null)
{
Iterator<? extends Object> iter = elements.iterator();
if(iter.hasNext())
{
builder.append( String.valueOf( iter.next() ) );
while(iter.hasNext())
{
builder
.append( separator )
.append( String.valueOf( iter.next() ) );
}
}
}
return builder.toString();
}
Android の場合: android.text.TextUtils には次のメソッドがあります。
public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)
区切り文字で結合されたトークンを含む文字列を返します。
tokens -- 結合する配列オブジェクト。object.toString() を呼び出すことにより、オブジェクトから文字列が形成されます。
完全を期すために、正規表現を受け入れるため、一般にString#splitを元に戻すことはできないことを付け加えたいと思います。
"hello__world".split("_+");
利回り["hello", "world"]
。
"hello_world".split("_+");
利回り["hello", "world"]
。
これらは、異なる開始点から同じ結果をもたらします。分割は 1 対 1 の操作ではないため、元に戻すことはできません。
これはすべて、パラメーターが正規表現ではなく固定文字列であると想定する場合、投稿された多くの回答の1つを使用して確実にこれを行うことができます。
以下のコードは基本的な考え方を示しています。ただし、これは最善の解決策ではありません。
public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty){
return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
}
public static String join(List<?> list, String delim, boolean ignoreEmpty) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
if (ignoreEmpty && !StringUtils.isBlank(list.get(i).toString())) {
sb.append(delim);
sb.append(list.get(i).toString().trim());
}
}
return sb.toString();
}
jdk8 を使用する場合は、@Nathaniel Johnson の回答を参照してください。
ここでの答えの多くは複雑であるか、簡単に読めないと思います。分岐予測が非常に効率的であるのに、なぜ単に if ステートメントを使用しないのでしょうか?
public static String join(List<String> fooList){
if (fooList.isEmpty()) return "";
StringBuilder sb = null;
for (String element : fooList) {
if (sb == null) {
sb = new StringBuilder();
} else {
sb.append(", ");
}
sb.append(element);
}
return sb.toString();
}
言及すべきことは、Apache がこのように内部に if ステートメントを含む単純な for ループを使用することです (最初の要素を知るためにインデックスとして配列を使用します)、openjdk 8 は同じことを行いますが、シンプルなループ。
これも悪くない :
public static String join(String delimitor,String ... subkeys) {
String result = null;
if(null!=subkeys && subkeys.length>0) {
StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
for(int idx=1;idx<subkeys.length;idx++) {
joinBuffer.append(delimitor).append(subkeys[idx]);
}
result = joinBuffer.toString();
}
return result;
}
私はこれを書きました:
public static String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<String> iter = col.iterator();
if (iter.hasNext())
sb.append(iter.next());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next());
}
return sb.toString();
}
Collection
は JSP でサポートされていないため、TLD について次のように記述しました。
public static String join(List<?> list, String delim) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
sb.append(delim);
sb.append(list.get(i).toString());
}
return sb.toString();
}
そしてファイルに入れ.tld
ます:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
<function>
<name>join</name>
<function-class>com.core.util.ReportUtil</function-class>
<function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
</function>
</taglib>
JSP ファイルで次のように使用します。
<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}
私はこれがもっと好きです:
public String join(Collection<String> strCollection, String delimiter) {
String joined = "";
int noOfItems = 0;
for (String item : strCollection) {
joined += item;
if (++noOfItems < strCollection.size())
joined += delimiter;
}
return joined;
}
これは私がこれまでに見つけた最も近い解決策です。(StringBuilderの代わりに生のStringオブジェクトを使用することについて心配する必要はありません。最近のJavaコンパイラーはとにかくStringBuilderを使用しますが、このコードはより読みやすくなっています)。