在 Java 中获取整数范围内的迭代器的最短方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/371026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shortest way to get an Iterator over a range of Integers in Java
提问by cretzel
What's the shortest way to get an Iterator over a range of Integers in Java? In other words, implement the following:
在 Java 中在一系列整数上获得迭代器的最短方法是什么?换句话说,实现以下内容:
/**
* Returns an Iterator over the integers from first to first+count.
*/
Iterator<Integer> iterator(Integer first, Integer count);
Something like
就像是
(first..first+count).iterator()
采纳答案by Bombe
Straight-forward implementation of your homework:
直接执行您的作业:
List<Integer> ints = new ArrayList<Integer>();
for (int i = 0; i < count; i++) {
ints.add(first + i);
}
回答by Joachim Sauer
Untested. Mapping that onto "min, count" is left as an exercise for the reader.
未经测试。将其映射到“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();
}
}
回答by Jon Skeet
If you actually want the shortest amount of code, then Bombe's answer is fine. However, it sucks memory for no good reason. If you want to implement it yourself, it would be something like:
如果您确实想要最短的代码量,那么 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();
}
}
回答by Hank Gay
It's generally considered good style to pass around Collection
and friends instead of Iterator
(see this FAQ entry), so I'd recommend something like
通常认为传递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 */
}
and then just use .iterator()
when you need to pass an Iterator
to whatever framework you're using.
然后.iterator()
在您需要将 an 传递Iterator
给您正在使用的任何框架时使用。
UPDATE: Obviously, this code isn't lazy. If you can't afford the extra memory overhead of storing (potentially) 2^32-1 Integer
s, you should use a different solution. Also, nothing about the type guarantees the range will be sorted (even though it is, based on the implementation). If you need to guarantee sorting, you could look into implementing SortedSetand backing it with a TreeSet, but it will take longer to build the range. Honestly, if you are that concerned with getting the details right, it might be worth your effort to look for a library. Tapestry has an internal version, for instance.
更新:显然,这段代码不是懒惰的。如果您负担不起存储(可能) 2^32-1Integer
秒的额外内存开销,您应该使用不同的解决方案。此外,关于类型的任何内容都不能保证范围会被排序(即使它是基于实现的)。如果您需要保证排序,您可以考虑实现SortedSet并使用TreeSet支持它,但构建范围需要更长的时间。老实说,如果您非常关心获得正确的细节,那么寻找图书馆可能是值得的。例如,Tapestry 有一个内部版本。
回答by Saintali
This implementation does not have a memory footprint.
此实现没有内存占用。
/**
* @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;
}
};
}
Edit:
编辑:
In Java 8 you can simply say:
在 Java 8 中,您可以简单地说:
IntStream.range(begin, end).iterator() // returns PrimitiveIterator.OfInt
or if you need the boxed version:
或者如果您需要盒装版本:
IntStream.range(begin, end).boxed().iterator() // returns Iterator<Integer>
回答by Lee
An example using the guava framework. Note that this will not materialize the set (although you have to read the ContiguousSet implementation to verify that).
使用番石榴框架的示例。请注意,这不会实现集合(尽管您必须阅读 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();
}
}
回答by btpka3
A sample using stream API in java 8:
在 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());
}
Without iterator, it could be:
没有迭代器,它可能是:
int first = 0;
int count = 10;
IntStream.range(first, first + count).forEach(i -> System.out.println(i));