web-dev-qa-db-ja.com

javaの拡張forループの最後の反復

ループが最後に反復しているかどうかを判断する方法はありますか。私のコードは次のようになります。

int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();

for(int i : array)
{
    builder.append("" + i);
    if(!lastiteration)
        builder.append(",");
}

さて、最後の繰り返しでコンマを追加したくないということです。これで、最後の繰り返しであるか、またはforループに固執しているか、または追跡するために外部カウンターを使用しているかどうかを判断する方法があります。

132
Mercurious

もう1つの方法は、first反復ではなく、iを追加する前にコンマを追加することです。 (ちなみに"" + iは使用しないでください。ここでは本当に連結したくないので、StringBuilderには完全に適切なappend(int)オーバーロードがあります。)

int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();

for (int i : array) {
    if (builder.length() != 0) {
        builder.append(",");
    }
    builder.append(i);
}

これの良いところは、どのIterableでも動作することです-常にインデックスを作成できるとは限りません。 (「カンマを追加して、最後に削除する」は、StringBuilderを実際に使用している場合の良い提案です。しかし、ストリームへの書き込みなどには機能しません。しかし、この正確な問題にはおそらく最善のアプローチです。 )

219
Jon Skeet

これを行う別の方法:

String delim = "";
for (int i : ints) {
    sb.append(delim).append(i);
    delim = ",";
}

更新:Java 8の場合、 Collectors

141
toolkit

常に追加する方が簡単な場合があります。そして、ループが完了したら、最後の文字を削除します。トン以下の条件もそのように。

インデックスがdeleteCharAt(int index)であるStringBuilderlength() - 1を使用できます

39
Dinah

たぶん、あなたは仕事のために間違ったツールを使用しています。

これはあなたがやっていることよりもマニュアルですが、少し「古い学校」ではないにしても、よりエレガントな方法です

 StringBuffer buffer = new StringBuffer();
 Iterator iter = s.iterator();
 while (iter.hasNext()) {
      buffer.append(iter.next());
      if (iter.hasNext()) {
            buffer.append(delimiter);
      }
 }
30
Omar Kooheji

これは、ほとんどの このStackOverflowの質問 の繰り返しです。必要なのはStringUtilsで、joinメソッドを呼び出します。

StringUtils.join(strArr, ',');
15
Phil H

別のソリューション(おそらく最も効率的な)

    int[] array = {1, 2, 3};
    StringBuilder builder = new StringBuilder();

    if (array.length != 0) {
        builder.append(array[0]);
        for (int i = 1; i < array.length; i++ )
        {
            builder.append(",");
            builder.append(array[i]);
        }
    }
14
bruno conde

明示的なループは、暗黙的なループよりも常にうまく機能します。

builder.append( "" + array[0] );
for( int i = 1; i != array.length; i += 1 ) {
   builder.append( ", " + array[i] );
}

長さゼロの配列を扱う場合に備えて、ifステートメントで全体をラップする必要があります。

6
S.Lott

シンプルに保ち、標準forループを使用します。

for(int i = 0 ; i < array.length ; i ++ ){
    builder.append(array[i]);
    if( i != array.length - 1 ){
        builder.append(',');
    }
}

または単にApacheを使用します commons-lang StringUtils.join()

5
Gareth Davis

それを古典的なインデックスループに変換する場合、はい。

または、最後のカンマを削除した後に削除することもできます。そのようです:

_int[] array = {1, 2, 3...};
StringBuilder

builder = new StringBuilder();

for(int i : array)
{
    builder.append(i + ",");
}

if(builder.charAt((builder.length() - 1) == ','))
    builder.deleteCharAt(builder.length() - 1);
_

私、私はただ StringUtils.join() from commons-lang を使用しています。

4
sblundy

Java.util.AbstractCollection.toString()に基づいて、デリミタを回避するために早期に終了します。

StringBuffer buffer = new StringBuffer();
Iterator iter = s.iterator();
for (;;) {
  buffer.append(iter.next());
  if (! iter.hasNext())
    break;
  buffer.append(delimiter);
}

それは効率的でエレガントですが、他の答えのいくつかほど自明ではありません。

3
13ren

クラスセパレーター が必要です。

_Separator s = new Separator(", ");
for(int i : array)
{
     builder.append(s).append(i);
}
_

クラスSeparatorの実装は単純です。空の文字列を返す最初の呼び出しを除き、toString()の呼び出しごとに返される文字列をラップします。

3
akuhn

解決策は次のとおりです。

int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();
bool firstiteration=true;

for(int i : array)
{
    if(!firstiteration)
        builder.append(",");

    builder.append("" + i);
    firstiteration=false;
}

最初の反復を探してください:)

2
FallenAvatar

さらに別のオプション。

StringBuilder builder = new StringBuilder();
for(int i : array)
    builder.append(',').append(i);
String text = builder.toString();
if (text.startsWith(",")) text=text.substring(1);
1
Peter Lawrey

ここで説明するソリューションの多くは、特に外部ライブラリに依存しているものよりも少し上にすぎません。私がいつも使用していたコンマ区切りリストを実現するための、すっきりした、明確なイディオムがあります。条件(?)演算子に依存しています。

編集:元のソリューションは正しいが、コメントによると最適ではない。もう一度試してください:

    int[] array = {1, 2, 3};
    StringBuilder builder = new StringBuilder();
    for (int i = 0 ;  i < array.length; i++)
           builder.append(i == 0 ? "" : ",").append(array[i]); 

配列の宣言とStringBuilderを含む4行のコードで、そこに行きます。

1
Julien Chastang

ツールキットで述べたように、Java 8で Collectors になりました。コードは次のようになります。

String joined = array.stream().map(Object::toString).collect(Collectors.joining(", "));

それはまさにあなたが探しているものであり、他の多くのことにも使えるパターンだと思います。

1
b1tw153

以下に、私が実行したSSCCEベンチマーク(実装しなければならないものに関連する)とこれらの結果を示します。

elapsed time with checks at every iteration: 12055(ms)
elapsed time with deletion at the end: 11977(ms)

少なくとも私の例では、反復ごとにチェックをスキップすることは、特に大量のデータについては目立って高速ではありませんが、isより高速です。

import Java.util.ArrayList;
import Java.util.List;


public class TestCommas {

  public static String GetUrlsIn(int aProjectID, List<String> aUrls, boolean aPreferChecks)
  {

    if (aPreferChecks) {

      StringBuffer sql = new StringBuffer("select * from mytable_" + aProjectID + " WHERE hash IN ");

      StringBuffer inHashes = new StringBuffer("(");
      StringBuffer inURLs = new StringBuffer("(");

      if (aUrls.size() > 0)
      {

      for (String url : aUrls)
      {

        if (inHashes.length() > 0) {
        inHashes.append(",");
        inURLs.append(",");
        }

        inHashes.append(url.hashCode());

        inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"");//.append(",");

      }

      }

      inHashes.append(")");
      inURLs.append(")");

      return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
    }

    else {

      StringBuffer sql = new StringBuffer("select * from mytable" + aProjectID + " WHERE hash IN ");

      StringBuffer inHashes = new StringBuffer("(");
      StringBuffer inURLs = new StringBuffer("(");

      if (aUrls.size() > 0)
      {

      for (String url : aUrls)
      {
        inHashes.append(url.hashCode()).append(","); 

        inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"").append(",");
      }

      }

      inHashes.deleteCharAt(inHashes.length()-1);
      inURLs.deleteCharAt(inURLs.length()-1);

      inHashes.append(")");
      inURLs.append(")");

      return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
    }

  }

  public static void main(String[] args) { 
        List<String> urls = new ArrayList<String>();

    for (int i = 0; i < 10000; i++) {
      urls.add("http://www.google.com/" + System.currentTimeMillis());
      urls.add("http://www.yahoo.com/" + System.currentTimeMillis());
      urls.add("http://www.bing.com/" + System.currentTimeMillis());
    }


    long startTime = System.currentTimeMillis();
    for (int i = 0; i < 300; i++) {
      GetUrlsIn(5, urls, true);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("elapsed time with checks at every iteration: " + (endTime-startTime) + "(ms)");

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 300; i++) {
      GetUrlsIn(5, urls, false);
    }
    endTime = System.currentTimeMillis();
    System.out.println("elapsed time with deletion at the end: " + (endTime-startTime) + "(ms)");
  }
}
1
Buffalo

別のアプローチは、配列の長さ(利用可能な場合)を別の変数に格納することです(毎回長さを再チェックするよりも効率的です)。次に、インデックスをその長さと比較して、最後のコンマを追加するかどうかを決定できます。

編集:別の考慮事項は、各文字列のコピーを引き起こす可能性のある最終文字を削除するパフォーマンスコストを、各反復で条件をチェックすることと比較検討することです。

0
Brian

ここで2つの代替パス:

1: Apache Commons String Utils

2:firstというブール値を保持し、trueに設定します。各反復で、firstがfalseの場合、コンマを追加します。その後、firstをfalseに設定します。

0
Paul Brinkley

この場合、それが最後の繰り返しかどうかを知る必要はありません。これを解決する方法はたくさんあります。 1つの方法は次のとおりです。

String del = null;
for(int i : array)
{
    if (del != null)
       builder.append(del);
    else
       del = ",";
    builder.append(i);
}
0
fastcodejava

固定配列なので、単純に拡張機能を回避する方が簡単です...オブジェクトがコレクションの場合、反復子は簡単になります。

int nums[] = getNumbersArray();
StringBuilder builder = new StringBuilder();

// non enhanced version
for(int i = 0; i < nums.length; i++){
   builder.append(nums[i]);
   if(i < nums.length - 1){
       builder.append(",");
   }   
}

//using iterator
Iterator<int> numIter = Arrays.asList(nums).iterator();

while(numIter.hasNext()){
   int num = numIter.next();
   builder.append(num);
   if(numIter.hasNext()){
      builder.append(",");
   }
}
0
AnthonyJClink

配列をコンマ区切りの配列に変換するだけの場合、多くの言語にはまさにこれのための結合関数があります。配列を各要素の間に区切り文字を持つ文字列に変換します。

0
Dinah