Dernière itération de la boucle améliorée en java

Est-il un moyen de déterminer si la boucle est une itération pour la dernière fois. Mon code ressemble à ceci:

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

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

maintenant, le truc c'est que je ne veux pas ajouter la virgule dans la dernière itération. Maintenant, il y a un moyen de déterminer si c'est la dernière itération ou si je suis coincé avec la boucle for ou en utilisant un compteur externe pour garder la trace.

127
demandé sur John Strood 2008-11-13 00:56:23

21 réponses

une autre alternative est d'ajouter la virgule avant d'ajouter i, mais pas sur la première itération. (S'il vous plaît ne pas utiliser "" + i , soit dit en passant - vous ne voulez pas vraiment concaténation ici, et StringBuilder a une surcharge d'ajout (int) parfaitement bonne.)

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

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

la bonne chose à propos de ceci est qu'il fonctionnera avec n'importe quel Iterable - vous ne pouvez pas toujours indexer les choses. ("Ajouter la virgule, puis l'enlever à la fin" est une belle suggestion lorsque vous utilisez vraiment StringBuilder - mais cela ne fonctionne pas pour des choses comme écrire à streams. C'est peut-être la meilleure approche pour ce problème précis.)

216
répondu Jon Skeet 2011-09-29 19:34:50

une autre façon de le faire:

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

mise à jour: pour Java 8, Vous avez maintenant Collectors

140
répondu toolkit 2015-03-16 03:01:27

Il pourrait être plus facile de toujours ajouter. Et puis, quand vous avez fini avec votre boucle, il suffit de supprimer le caractère final. Des tonnes de moins de conditionnels.

vous pouvez utiliser StringBuilder 's deleteCharAt(int index) avec l'index étant length() - 1

39
répondu Dinah 2010-04-28 18:05:42

Peut-être que vous utilisez le mauvais outil pour le Travail.

C'est plus manuel que ce que vous faites, mais c'est plus élégant si pas un peu "vieille école"

 StringBuffer buffer = new StringBuffer();
 Iterator iter = s.iterator();
 while (iter.hasNext()) {
      buffer.append(iter.next());
      if (iter.hasNext()) {
            buffer.append(delimiter);
      }
 }
29
répondu Omar Kooheji 2008-11-12 22:13:29

c'est presque une répétition de cette question sur L'écoulement des piles . Ce que vous voulez est StringUtils , et d'appeler le joindre méthode.

StringUtils.join(strArr, ',');
15
répondu Phil H 2017-05-23 12:26:33

une autre solution (peut-être la plus efficace)

    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
répondu bruno conde 2008-11-13 13:49:40

les boucles explicites fonctionnent toujours mieux que les boucles implicites.

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

vous devriez envelopper le tout dans un if-statement juste au cas où vous avez affaire à un tableau de longueur zéro.

6
répondu S.Lott 2008-11-12 22:05:33

keep it simple et l'utilisation d'un standard pour la boucle:

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

ou tout simplement utiliser apache commons-lang StringUtils.join ()

5
répondu Gareth Davis 2012-03-09 18:45:33

si vous le convertissez en boucle d'index classique, Oui.

ou vous pouvez supprimer la dernière virgule après que c'est fait. Comme ceci:

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);

Moi, je viens d'utiliser StringUtils.join() à partir de commons-lang .

4
répondu sblundy 2009-10-07 21:22:09

Vous avez besoin de Classe Séparateur .

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

l'application de la classe Separator est simple. Il enroule une corde qui est retournée sur chaque appel de toString() sauf pour le premier appel, qui renvoie une corde vide.

3
répondu akuhn 2008-11-16 16:55:54

basé sur java.util.AbstractCollection.toString (), il sort tôt pour éviter le délimiteur.

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

, C'est efficace et élégant, mais pas aussi évident que certains des autres réponses.

3
répondu 13ren 2009-03-21 12:13:06

Voici une solution:

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;
}

rechercher la première itération :)  

2
répondu FallenAvatar 2013-09-26 08:45:39

encore une autre option.

StringBuilder builder = new StringBuilder();
for(int i : array)
    builder.append(',').append(i);
String text = builder.toString();
if (text.startsWith(",")) text=text.substring(1);
1
répondu Peter Lawrey 2009-03-21 12:25:45

beaucoup des solutions décrites ici sont un peu exagérées, IMHO, surtout celles qui s'appuient sur des bibliothèques externes. Il y a un beau langage propre et clair pour réaliser une liste séparée par des virgules que j'ai toujours utilisée. Elle repose sur le conditionnel (?) exploitant:

Edit : solution originale correcte, mais non optimale selon les commentaires. Essayer une deuxième fois:

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

voilà, en 4 lignes de code y compris la déclaration du tableau et du StringBuilder.

1
répondu Julien Chastang 2009-03-22 05:35:42

voici un benchmark SSCCE que j'ai fait (lié à ce que j'ai dû mettre en œuvre) avec ces résultats:

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

sur mon exemple au moins, sauter le contrôle à chaque itération n'est pas sensiblement plus rapide en particulier pour les volumes sains de données, mais il est plus rapide.

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
répondu Buffalo 2014-08-01 14:58:26

comme toolkit mentionné, en Java 8 nous avons maintenant Collectors . Voici à quoi ressemblerait le code:

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

je pense que c'est exactement ce que vous cherchez, et c'est un motif que vous pourriez utiliser pour beaucoup d'autres choses.

1
répondu b1tw153 2016-11-11 01:24:50

une autre approche consiste à stocker la longueur du tableau (si disponible) dans une variable distincte (ce qui est plus efficace qu'une nouvelle vérification de la longueur à chaque fois). Vous pouvez ensuite comparer votre index à cette longueur pour déterminer s'il faut ajouter ou non la virgule finale.

éditer: une autre considération est de peser le coût de performance d'enlever un caractère final (qui peut causer une copie de chaîne de caractères) contre avoir un conditionnel être vérifié dans chaque itération.

0
répondu Brian 2008-11-12 22:06:10

si vous transformez seulement un tableau en un tableau délimité par une virgule, Beaucoup de langues ont une fonction jointure pour exactement cela. Il transforme un tableau en chaîne avec un délimiteur entre chaque élément.

0
répondu Dinah 2008-11-12 22:44:58

Dans ce cas, il n'y a vraiment pas besoin de savoir si c'est la dernière répétition. Il existe de nombreuses façons que nous pouvons résoudre ce problème. Une solution serait:

String del = null;
for(int i : array)
{
    if (del != null)
       builder.append(del);
    else
       del = ",";
    builder.append(i);
}
0
répondu fastcodejava 2011-05-24 06:58:48

deux chemins alternatifs ici:

1: Apache Commons String Utils

2: garder un booléen appelé first , placé à true. Dans chaque itération, si first est false, ajoutez votre virgule; après cela, mettez first à false.

0
répondu Paul Brinkley 2016-05-30 12:50:16

depuis son un tableau fixe, il serait plus facile tout simplement d'éviter le rehaussé pour... Si l'Objet est une collection d'un itérateur serait plus facile.

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
répondu AnthonyJClink 2017-06-15 02:55:50