这是我编写的implements Iterable<Integer>
课程,用于算术系列课程(从start
到stop
,步骤为step
)
package com.example.test;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
public class ArithmeticSeries implements Iterable<Integer>
{
final private int start, step, stop;
public int getStart() { return this.start; }
public int getStep() { return this.step; }
public int getStop() { return this.stop; }
public ArithmeticSeries(int start, int step, int stop)
{
this.start = start;
this.step = step;
this.stop = stop;
}
@Override public Iterator<Integer> iterator()
{
return new AbstractIterator<Integer>() {
private Integer n = null;
@Override protected Integer computeNext() {
int next;
if (this.n == null)
{
next = getStart();
}
else
{
next = this.n + getStep();
if ((getStep() > 0 && next > getStop())
|| (getStep() < 0 && next < getStop()))
return endOfData();
}
this.n = next;
return next;
}
};
}
@Override public String toString() {
return getStart()+":"+getStep()+":"+getStop();
}
public static void main(String[] args) {
Iterable<Integer> range = new ArithmeticSeries(100,-1,80);
System.out.println(range);
for (int i : range)
System.out.println(i);
}
}
有没有办法实现更优雅的iterator()
?我不喜欢null检查和使用Integer
(替代将是一个额外的标志boolean firstTime
),它似乎是错误的。
答案 0 :(得分:4)
return new AbstractIterator<Integer>() {
int next = getStart();
@Override protected Integer computeNext() {
if (isBeyondEnd(next)) {
return endOfData();
}
Integer result = next;
next = next + getStep();
return result;
}
};
如果您愿意,您可以将其实现为不可变List<Integer>
。如果您延长AbstractList
,则Iterator
会为您处理。实际上,我认为AbstractList
真的是最好的方式。全班看起来像这样(我没有检查过它在所有情况下都能正常工作):
public class ArithmeticSeries extends AbstractList<Integer> {
private final int start;
private final int step;
private final int size;
public ArithmeticSeries(int start, int end, int step) {
this.start = start;
this.step = (start < end) ? step : -step;
this.size = (end - start) / this.step + 1;
}
@Override public Integer get(int index) {
return start + step * index;
}
@Override public int size() {
return size;
}
}
答案 1 :(得分:2)
您可以使用Function抽象连续值,使用Predicate控制迭代结束,最终创建Unfold实现:
public final class UnfoldIterator<E> implements Iterator<E> {
public static <E> Iterator<E> unfold(E initial, Function<? super E, ? extends E> next, Predicate<? super E> finished) {
return new UnfoldIterator<E>(initial, next, finished)
}
private final Function<? super E, ? extends E> next;
private final Predicate<? super E> finished;
private E element;
public UnfoldIterator(E initial, Function<? super E, ? extends E> next, Predicate<? super E> finished) {
super();
this.next = next;
this.finished = finished;
this.element = initial;
}
@Override protected Integer computeNext() {
if (finished.apply(element)) {
return endOfData();
}
E result = element;
element = next.apply(element);
return result;
}
}
然后ArithmeticSeries变为:
public Iterable<Integer> series(final int start, final int step, final int stop) {
return new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new UnfoldIterator<Integer>(start, new Function<Integer, Integer>() {
public Integer apply(Integer from) {
return from - step;
}
}, new Predicate<Integer>() {
public boolean apply(Integer input) {
return input >= stop;
}
});
}
};
}
当然,代码现在似乎更复杂,但是通过适当的基本函数进行比较和代数,调用变得更加清晰:
return unfold(start, subtractBy(step), not(lessThan(stop)));
答案 2 :(得分:1)
我认为番石榴问题的最佳工具是AbstractLinkedIterator
。您的示例的实现如下所示:
final Iterator<Integer> series = new AbstractLinkedIterator<Integer>(100) {
@Override protected Integer computeNext(final Integer previous) {
return previous == 80 ? null : previous - 1;
}
};
while (series.hasNext()) {
System.out.println(series.next());
}
您可以轻松地为此迭代器创建Iterable
适配器,例如像这样:
package sk.the0retico.guava;
import java.util.Iterator;
import com.google.common.base.Function;
import com.google.common.collect.AbstractLinkedIterator;
public class LinkedIterable<T> implements Iterable<T> {
public static final <T> Iterable<T> from(final T first,
final Function<T, T> computeNext) {
return new LinkedIterable<T>(first, computeNext);
}
public static void main(final String[] args) {
final Iterable<Integer> series = LinkedIterable.from(100,
new Function<Integer, Integer>() {
@Override public Integer apply(final Integer input) {
return input == 80 ? null : input - 1;
}
});
for (final Integer value : series) {
System.out.println(value);
}
}
private final Function<T, T> computeNext;
private final T first;
public LinkedIterable(final T first, final Function<T, T> computeNext) {
this.first = first;
this.computeNext = computeNext;
}
@Override public Iterator<T> iterator() {
return new AbstractLinkedIterator<T>(first) {
@Override protected T computeNext(final T previous) {
return computeNext.apply(previous);
}
};
}
}
但是,这种方法对返回null
的提供函数进行了特殊约束。