Последняя итерация расширенного цикла в java

Есть ли способ определить, выполняется ли цикл в последний раз. Мой код выглядит примерно так:

int[] array = {1, 2, 3...}; StringBuilder builder = new StringBuilder(); for(int i : array) { builder.append("" + i); if(!lastiteration) builder.append(","); } 

Теперь дело в том, что я не хочу добавлять запятую в последнюю итерацию. Теперь есть способ определить, является ли это последней итерацией, или я придерживаюсь цикла for или используя внешний счетчик для отслеживания.

Другой альтернативой является добавление запятой перед добавлением 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, но это не работает для таких вещей, как запись в streamи. Возможно, это лучший подход для этой точной проблемы. )

Другой способ сделать это:

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

Обновление: для Java 8 у вас теперь есть Collectors

Это может быть проще всегда добавлять. И затем, когда вы закончите свой цикл, просто удалите финальный символ. Тонны меньше условностей тоже.

Вы можете использовать StringBuilder ‘s deleteCharAt(int index) с индексом length() - 1

Возможно, вы используете неправильный инструмент для задания.

Это более руководство, чем то, что вы делаете, но это более элегантно, если не немного «старая школа»,

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

Это почти повторение этого вопроса StackOverflow . Вы хотите использовать StringUtils и вызвать метод join .

 StringUtils.join(strArr, ','); 

Другое решение (возможно, наиболее эффективное)

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

Явные циклы всегда работают лучше, чем неявные.

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

Вы должны обернуть все это в if-statement на всякий случай, если вы имеете дело с массивом нулевой длины.

держите его простым и используйте стандарт для цикла:

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

или просто используйте apache commons-lang StringUtils.join ()

Если вы конвертируете его в classический индексный цикл, да.

Или вы можете просто удалить последнюю запятую после ее завершения. Вот так:

 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() из commons-lang .

Вам нужен Class Separator .

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

Реализация classа Separator выполняется прямо. Он обертывает строку, возвращаемую при каждом вызове toString() за исключением первого вызова, который возвращает пустую строку.

Основываясь на java.util.AbstractCollection.toString (), он выйдет раньше, чтобы избежать разделителя.

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

Это эффективный и элегантный, но не такой очевидный, как некоторые другие ответы.

Вот решение:

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

Ищите первую итерацию 🙂

Еще один вариант.

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

Многие из описанных здесь решений немного выше, IMHO, особенно те, которые полагаются на внешние библиотеки. Существует хорошая чистая, ясная идиома для достижения списка, разделенного запятыми, которые я всегда использовал. Он опирается на условный (?) Оператор:

Изменить : Исходное решение правильно, но не оптимально в соответствии с комментариями. Повторяя второй раз:

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

Там вы идете в 4 строках кода, включая объявление массива и StringBuilder.

Ниже приведен тест SSCCE, который я выполнил (связанный с тем, что мне нужно было реализовать) с этими результатами:

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

На моем примере, по крайней мере, пропуская проверку на каждой итерации не заметно быстрее, особенно для разумных объемов данных, но она быстрее.

 import java.util.ArrayList; import java.util.List; public class TestCommas { public static String GetUrlsIn(int aProjectID, List 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 urls = new ArrayList(); 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)"); } } 

Как упоминалось в пакете инструментов, в Java 8 теперь есть Collectors . Вот как выглядит код:

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

Я думаю, что делает именно то, что вы ищете, и это образец, который вы могли бы использовать для многих других вещей.

Другой подход заключается в том, чтобы длина массива (если доступна) хранилась в отдельной переменной (более эффективная, чем повторная проверка длины каждый раз). Затем вы можете сравнить свой индекс с этой длиной, чтобы определить, следует ли добавлять окончательную запятую.

EDIT: Еще одно соображение – это взвешивание стоимости исполнения для удаления окончательного символа (что может привести к копированию строки) против того, чтобы условие было проверено на каждой итерации.

Если вы только превращаете массив в массив с разделителями-запятыми, на многих языках для этого есть функция соединения. Он превращает массив в строку с разделителем между каждым элементом.

В этом случае нет необходимости знать, является ли это последним повторением. Есть много способов решить эту проблему. Один из способов:

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

Здесь есть два альтернативных пути:

1: Утилиты String Apache

2: сначала вызвать логическое имя, установленное в true. На каждой итерации, если first ложно, добавьте запятую; после этого first установите значение false.

Поскольку это фиксированный массив, было бы проще просто избежать расширения для … Если Object представляет собой коллекцию, то iteratorу будет проще.

 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 numIter = Arrays.asList(nums).iterator(); while(numIter.hasNext()){ int num = numIter.next(); builder.append(num); if(numIter.hasNext()){ builder.append(","); } } в 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 numIter = Arrays.asList(nums).iterator(); while(numIter.hasNext()){ int num = numIter.next(); builder.append(num); if(numIter.hasNext()){ builder.append(","); } } 
Давайте будем гением компьютера.