Когда расширенный цикл for (цикл foreach) был добавлен в Java, он был настроен для работы с целевым объектом либо массива, либо Iterable
.
for ( T item : /*T[] or Iterable<? extends T>*/ ) {
//use item
}
Это прекрасно работает для классов Collection, которые реализуют только один тип итерации и, следовательно, имеют единственный метод iterator()
.
Но я нахожусь невероятно расстроенным из-за странного случая, когда я хочу использовать нестандартный итератор из класса Collection. Например, недавно я пытался помочь кому-нибудь использовать Deque
в качестве LIFO / стека, но затем печатать элементы в порядке FIFO. Я был вынужден сделать это:
for (Iterator<T> it = myDeque.descendingIterator(); it.hasNext(); ) {
T item = it.next();
//use item
}
Я теряю преимущества цикла for-each. Это не просто нажатия клавиш. Мне не нравится выставлять итератор, если мне это не нужно, поскольку легко совершить ошибку, вызвав it.next()
дважды и т. Д.
Теперь в идеале я думаю, что цикл for-each должен был бы также принять Iterator
. Но это не так. Так есть ли идиоматический способ использования цикла for-each в этих обстоятельствах? Я также хотел бы услышать предложения, которые используют библиотеки общих коллекций, такие как Guava.
Лучшее, что я могу придумать в отсутствие вспомогательного метода / класса:
for ( T item : new Iterable<T>() { public Iterator<T> iterator() { return myDeque.descendingIterator(); } } ) {
//use item
}
Что не стоит использовать.
Я бы хотел, чтобы у Гуавы было что-то вроде Iterables.wrap
, чтобы сделать это идиоматическим, но ничего подобного не нашел. Очевидно, что я мог бы свернуть свою собственную обертку Iterator через метод класса или вспомогательный метод. Есть другие идеи?
Редактировать: Как примечание, кто-нибудь может дать вескую причину того, почему расширенный цикл for не мог просто принять Iterator
? Это, вероятно, во многом помогло бы мне жить с текущим дизайном.