Упростить цикл [закрытый]
Каков будет ваш предпочтительный тип цикла для такого случая:
StringBuilder sb = new StringBuilder();
for(Integer id : idList) {
sb.append("?,");
}
Вкратце: в зависимости от размера списка я хочу добавить материал в String. В приведенном выше примере выдается предупреждение «неиспользуемая переменная».
Я думаю об этих альтернативах:
for(int i=0; i<idList.size(); i++) {
// ...
}
Мне не нравится все лишнее написание там ...
Iterator it = idList.iterator();
while(it.hasNext()) {
// ...
it.next();
}
Сам контур цикла выглядит неплохо, но в итоге я набираю много дополнительного кода (получаю итератор, переходя к следующему элементу ...)
То, что я хотел бы сделать, будет примерно таким:
for(idList) {
// ...
}
Есть ли лучший стиль /Какой лучший стиль для такого цикла?
5 ответов
Я бы использовал обычный метод повторения строк:
String s = repeat("?,", idList.size());
К сожалению, Java не имеет такого метода в стандартном API. Поэтому вы можете написать один:
String repeat(String s, count i) {
StringBuilder sb = new StringBuilder();
while (i-- > 0) {
ab.append(s);
}
return sb.toString();
}
или использовать один, предоставленный несколькими стандартными API-интерфейсами надстройки, такими как Apache Commons ' StringUtils.repeat()
Второй пример, безусловно, самый ясный в выражении вашего намерения. Вы хотите сделать что-то несколько раз, в этом случае idList.size()
.
for( int i = 0; i < idList.size(); ++i ) {
// ...
}
В третьем вы в основном просто пишете то, что уже генерирует первый пример, так что это определенно не улучшение.
У вас есть точка, в которой цикл for является скорее большой конструкцией кода, которая выражает просто выполнение куска кода в несколько раз. Ruby's times
, производится именно для этой цели. На других языках существуют некоторые конструкции кода, которые могут вам помочь. Методы расширения в C # позволяют создать аналогичный оператор, как оператор times
Ruby.
Для Java я не верю, что возможен более сжатый синтаксис, поскольку закрытия по умолчанию не поддерживаются в Java.
Как в ответе RoToRa , простой String
Вспомогательный класс, содержащий функцию Repeat
, скорее всего, самый чистый решение для вас. Он не предоставляет функции для повторения любого типа или операции, но он обеспечивает сжатый синтаксис, который вы ищете.
Я предлагаю использовать Strings.repeat () из библиотеки Google Guava:
String result = Strings.repeat("?,", idList.size());
Я бы пошел с первой альтернативой и использовал @SuppressWarnings
.
Если вам нужен этот шаблон чаще, как насчет объектно-ориентированного решения:
public static class Repeat<T> implements Iterable<T> {
private final T[] ts;
private final int n;
public Repeat(int n, T ... ts) {
this.ts = ts;
this.n = n;
}
public Iterator<T> iterator() {
return new Iterator<T>() {
int count = 0;
public boolean hasNext() {
return count < n;
}
public T next() {
if (! hasNext()) {
throw new NoSuchElementException();
}
return ts[(count++) % ts.length];
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
};
}
public static <U> Repeat<U> repeat(int n, U ... us) {
return new Repeat<U>(n, us);
}
}
//usage
import static blabla.Repeat.*;
...
for(String s : repeat(idList.size(), "?,")) {
sb.append(s);
}
Я лично использовал бы вторую версию, т. е. цикл for
, потому что он яснее. Первый пример выглядит так: вы ввели ошибку, не используя id, третий добавляет две дополнительные строки кода, но не так уж плохо на глаза.
Я думаю, что я бы также создал локальный кеш size()
, чтобы вы могли избежать вызова функции на каждой итерации цикла , Но это компромисс между скоростью, размером списка, читабельностью и изменением размера списка во время цикла.
int size = idList.size();
for (int i = 0; i < size; ++i) {...}
Если это сильно называемый внутренний цикл, сэкономить несколько десятков тысяч вызовов функций, чтобы вернуть «константу», можно сэкономить некоторое время. Но если вы сделаете что-то подобное, может быть стоит сказать, почему вы сделали это «по-другому» с нормальным ожидаемым способом.
Мне нравится петли, потому что они очень самодостаточны; вы получаете начальное значение, конечное условие и операцию увеличения в одной строке, тогда как цикл while требует поиска для «++
» где-то в течение блокировать себя.
Я считаю, что держать ваше намерение простым и ясным, более важно идти вперед, когда ваш код должен поддерживаться. Не забудьте указать код, как будто человек, поддерживающий ваш код, является серийным убийцей, который знает, где вы живете.