使用 Guava Iterables.cycle 作为循环列表实现

Using Guava Iterables.cycle as a circular list impl

我有一个 List<Widget> 并且正在寻找最 efficient/elegant 的解决方案来一次又一次地循环它(有点像循环算法):

// Returns a list of 20 widgets, with an id of 1 - 20 respectively.
List<Widget> widgets = getWidgets();
Widget widget = pickWidget(); // Returns the 1st widget with id = 1.
widget = pickWidget(); // Returns the 2nd widget with id = 2.
widget = pickWidget(); // Return the 3rd widget with id = 3.
// ..etc.
widget = pickWidget(); // Returns the 19th widget with id = 19.
widget = pickWidget(); // Returns the 20th widget with id = 20.
widget = pickWidget(); // Returns the 1st widget with id = 1 (it cycle back).

这就是用法,我能找到的最好的实现是 Guava 的 Iterables.cycle(...):

Widget pickWidget() {
    for(Widget w : Iterables.cycle(widgets)) {
        return w;
    }
}

问题是 cycle 没有在 widgets 中留下标记,因此它可以 "remember" 在上次调用 pickWidget() 时放手。

有什么想法吗? Apache 的 CircularFifoQueue 似乎很接近但没有雪茄,因为我不想从队列中弹出任何东西,我只希望它在调用时一次又一次地循环遍历同一个列表。

它不会留下标记,因为这不是 iterator() 的目的 -- 它不会在调用之间保留任何内容。

怎么样:

private int pos = 0;
Widget pickWidget() {
    return widgets.get(pos++ % widets.size());
}

不需要留下任何标记。 cycle() 返回的 Iterable 的迭代器在内部保留该标记。您只需要保留对此迭代器的引用:

private Iterator<Widget> cyclingIterator = Iterables.cycle(widgets).iterator();

public Widget pick() {
    return cyclingIterator.next();
}

或者简单地说,因为您实际上不需要 Iterable,而只需要迭代器:

private Iterator<Widget> cyclingIterator = Iterators.cycle(widgets);

public Widget pick() {
    return cyclingIterator.next();
}