web-dev-qa-db-ja.com

Java)の整数の範囲でイテレータを取得する最短の方法

Javaで整数の範囲でイテレータを取得する最短の方法は何ですか?つまり、次のように実装します。

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

何かのようなもの

(first..first+count).iterator()
23
cretzel

宿題の簡単な実装:

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

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

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

テストされていません。それを「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();
  }
}
15
Joachim Sauer

実際に最短量のコードが必要な場合は、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();
    }
}
9
Jon Skeet

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();
    }
}
7
Lee

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));
4
btpka3

一般に、Collectionの代わりにIteratorとその友達を渡すのが良いスタイルだと考えられています( this FAQ entry を参照)。 dのようなものをお勧めします

_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 Integersを(潜在的に)格納するための追加のメモリオーバーヘッドを許容できない場合は、別のソリューションを使用する必要があります。また、タイプについては、範囲がソートされることを保証するものは何もありません(実装に基づいていますが)。並べ替えを保証する必要がある場合は、 SortedSet を実装し、 TreeSet でバックアップすることを検討できますが、範囲の構築には時間がかかります。正直なところ、詳細を正しく理解することに関心がある場合は、ライブラリを探す価値があるかもしれません。たとえば、タペストリーには 内部バージョン があります。

2
Hank Gay