25

Javaで整数の範囲にわたってイテレータを取得する最短の方法は何ですか? つまり、以下を実装します。

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

何かのようなもの

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

7 に答える 7

76

この実装にはメモリ フットプリントがありません。

/**
 * @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>
于 2011-07-26T10:49:00.357 に答える
16

未テスト。それを「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();
  }
}
于 2008-12-16T11:28:34.463 に答える
9

実際に最小限のコードが必要な場合は、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();
    }
}
于 2008-12-16T11:30:09.420 に答える
7

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();
    }
}
于 2011-10-31T16:27:33.763 に答える
4

宿題の簡単な実装:

List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
    ints.add(first + i);
}
于 2008-12-16T11:22:14.880 に答える
4

Java 8 でストリーム API を使用するサンプル:

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));
于 2016-04-20T11:17:18.280 に答える
2

一般的には、 (この FAQ エントリを参照してください)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ます。

更新: 明らかに、このコードは怠惰ではありません。(潜在的に) 2^32-1 秒を格納する余分なメモリ オーバーヘッドを許容できない場合はInteger、別のソリューションを使用する必要があります。また、タイプについては、範囲がソートされることを保証するものは何もありません (実装に基づいていても)。並べ替えを保証する必要がある場合は、SortedSetを実装してTreeSetでサポートすることを検討できますが、範囲を構築するには時間がかかります。正直なところ、詳細を正しく把握することに関心がある場合は、ライブラリを探す努力をする価値があるかもしれません。たとえば、 Tapestry には内部バージョンがあります。

于 2008-12-16T11:59:01.017 に答える