Ответ 1
Прямая реализация вашей домашней работы:
List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
ints.add(first + i);
}
Какой самый короткий способ получить Iterator по целому ряду целых чисел в Java? Другими словами, выполните следующее:
/**
* Returns an Iterator over the integers from first to first+count.
*/
Iterator<Integer> iterator(Integer first, Integer count);
Что-то вроде
(first..first+count).iterator()
Прямая реализация вашей домашней работы:
List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
ints.add(first + i);
}
Эта реализация не имеет области памяти.
/**
* @param begin inclusive
* @param end exclusive
* @return list of integers from begin to end
*/
public static List<Integer> range(final int begin, final int end) {
return new AbstractList<Integer>() {
@Override
public Integer get(int index) {
return begin + index;
}
@Override
public int size() {
return end - begin;
}
};
}
В Java 8 вы можете просто сказать:
IntStream.range(begin, end).iterator() // returns PrimitiveIterator.OfInt
или если вам нужна версия в коробке:
IntStream.range(begin, end).boxed().iterator() // returns Iterator<Integer>
непроверенная. Отображение этого значения на "min, count" оставлено как упражнение для читателя.
public class IntRangeIterator implements Iterator<Integer> {
private int nextValue;
private final int max;
public IntRangeIterator(int min, int max) {
if (min > max) {
throw new IllegalArgumentException("min must be <= max");
}
this.nextValue = min;
this.max = max;
}
public boolean hasNext() {
return nextValue <= max;
}
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return Integer.valueOf(nextValue++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Если вы действительно хотите получить кратчайший код, тогда ответ Bombe в порядке. Тем не менее, он сосет память без уважительной причины. Если вы хотите реализовать его самостоятельно, это будет примерно так:
import java.util.*;
public class IntegerRange implements Iterator<Integer>
{
private final int start;
private final int count;
private int position = -1;
public IntegerRange(int start, int count)
{
this.start = start;
this.count = count;
}
public boolean hasNext()
{
return position+1 < count;
}
public Integer next()
{
if (position+1 >= count)
{
throw new NoSuchElementException();
}
position++;
return start + position;
}
public void remove()
{
throw new UnsupportedOperationException();
}
}
Пример использования оболочки guava. Обратите внимание, что это не материализует набор (хотя вы должны прочитать реализацию ContiguousSet, чтобы убедиться в этом).
import com.google.common.collect.ContiguousSet;
import com.google.common.collect.DiscreteDomain;
import com.google.common.collect.DiscreteDomains;
class RangeIterator {
public Iterator<Integer> range(int start, int length) {
assert length > 0;
Range<Integer> dim_range = Ranges.closedOpen(start, start + length);
DiscreteDomain<Integer> ints = DiscreteDomains.integers();
ContiguousSet<Integer> dim = dim_range.asSet(ints);
return dim.iterator();
}
}
Пример с использованием API потока в java 8:
int first = 0;
int count = 10;
Iterator<Integer> it = IntStream.range(first, first + count).iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Без итератора это может быть:
int first = 0;
int count = 10;
IntStream.range(first, first + count).forEach(i -> System.out.println(i));
Как правило, считается хорошим стилем, чтобы обойти Collection
и друзей вместо Iterator
(см. этот раздел часто задаваемых вопросов), поэтому я Рекомендуем что-то вроде
public final class IntegerRange implements Set<Integer> {
final LinkedHashSet<Integer> backingList;
public IntegerRange(final int start, final int count) {
backingList = new LinkedHashSet(count, 1.0f);
for (int i=0; i < count; i++) {
backingList.set(i, start + i);
}
}
/** Insert a bunch of delegation methods here */
}
а затем просто используйте .iterator()
, когда вам нужно передать Iterator
во все рамки, которые вы используете.
UPDATE: Очевидно, что этот код не ленив. Если вы не можете позволить себе дополнительные издержки памяти для хранения (потенциально) 2 ^ 32-1 Integer
s, вы должны использовать другое решение. Кроме того, ничего о типе не гарантирует, что диапазон будет отсортирован (хотя он и основан на реализации). Если вам нужно гарантировать сортировку, вы можете изучить SortedSet и выполнить ее с помощью TreeSet, но для построения диапазона потребуется больше времени. Честно говоря, если вы заинтересованы в правильном оформлении деталей, возможно, вам стоит поискать библиотеку. Например, у Tapestry есть внутренняя версия.