Самый короткий способ получить Iterator по целому ряду целых чисел в Java

Какой самый короткий способ получить Iterator по целому ряду целых чисел в Java? Другими словами, выполните следующее:

/** 
* Returns an Iterator over the integers from first to first+count.
*/
Iterator<Integer> iterator(Integer first, Integer count);

Что-то вроде

(first..first+count).iterator()

Ответ 1

Прямая реализация вашей домашней работы:

List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
    ints.add(first + i);
}

Ответ 2

Эта реализация не имеет области памяти.

/**
 * @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>

Ответ 3

непроверенная. Отображение этого значения на "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();
  }
}

Ответ 4

Если вы действительно хотите получить кратчайший код, тогда ответ 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();
    }
}

Ответ 5

Пример использования оболочки 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();
    }
}

Ответ 6

Пример с использованием 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));

Ответ 7

Как правило, считается хорошим стилем, чтобы обойти 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 есть внутренняя версия.