2015-09-14 1 views
2

У меня есть List<Widget> и я ищу наиболее эффективным/элегантное решение петли над ним, снова и снова (вроде как алгоритм циклического перебора):Использование Guava Iterables.cycle в круговом списке осущ

// 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). 

это использование, для реализации лучшее, что я смог найти в гуавы-х Iterables.cycle(...):

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

проблема заключается в том, что cycle не оставляет маркер внутри widgets так, что он может «вспомнить», где это позволяло в последний раз был вызван pickWidget().

Любые идеи здесь? Apache CircularFifoQueue кажется близким, но без сигары, так как я не хочу, чтобы что-то выходило из очереди, я просто хочу, чтобы он снова и снова перебирал один и тот же список, как его называют.

ответ

9

Он не должен оставлять никаких маркер. Итератор 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(); 
} 
-1

Он не оставляет маркер, потому что это не цель iterator() - он не сохраняется между вызовами.

Как насчет:

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

Err, это именно цель Итератор, и он сохраняется между вызовами. –

+0

@JBNizet Объект итератора сохраняет состояние, метод 'iterator()' не делает, поскольку он обычно будет давать вам новый объект :) – mvd

+0

У вашего начального сообщения не было круглых скобок после итератора. Поскольку итератор сохраняет состояние, почему бы не использовать его? Ваш метод забывает увеличивать pos и будет очень неэффективным, если список не RandomAccess. –

Смежные вопросы