Итерация по списку в обратном порядке в java [дубликат]
этот вопрос уже есть ответ здесь:
я переношу часть кода, чтобы использовать дженерики. Одним из аргументов для этого является то, что цикл for намного чище, чем отслеживание индексов или использование явного итератор.
примерно в половине случаев список (ArrayList) повторяется в обратном порядке с помощью индекса сегодня.
может кто-то предложить более чистый способ сделать это (так как мне не нравится indexed for loop при работе с коллекциями), хотя он работает?
for (int i = nodes.size() - 1; i >= 0; i--) {
final Node each = (Node) nodes.get(i);
...
}
Примечание: я не могу добавить никаких новых зависимостей за пределами JDK.
15 ответов:
попробуйте это:
// Substitute appropriate type. ArrayList<...> a = new ArrayList<...>(); // Add elements to list. // Generate an iterator. Start just after the last element. ListIterator li = a.listIterator(a.size()); // Iterate in reverse. while(li.hasPrevious()) { System.out.println(li.previous()); }
гуавы предложения
Lists#reverse(List)иImmutableList#reverse(). Как и в большинстве случаев для гуавы, первые делегируют последнему, если аргументImmutableList, Так что вы можете использовать в всех случаях. Они не создают новые копии списка, а просто "перевернутые представления" его.пример
List reversed = ImmutableList.copyOf(myList).reverse();
Я не думаю, что это возможно с помощью синтаксиса цикла. Единственное, что я могу предложить-это сделать что-то вроде:
Collections.reverse(list); for (Object o : list) { ... }... но я бы не сказал, что это "чище", учитывая, что это будет менее эффективным.
Вариант 1: вы думали о реверсировании списка с помощью коллекции#reverse () и затем с помощью foreach?
конечно, вы также можете выполнить рефакторинг кода, таких, что список правильно упорядочены таким образом, вы не должны обратить его, который использует дополнительное пространство/время.
EDIT:
Вариант 2: в качестве альтернативы, не могли бы вы использовать Deque вместо ArrayList? Это позволит вам перебирать вперед и назад
EDIT:
Вариант 3: Как предлагали другие, вы можете написать итератор, который будет проходить через список в обратном порядке, вот пример:
import java.util.Iterator; import java.util.List; public class ReverseIterator<T> implements Iterator<T>, Iterable<T> { private final List<T> list; private int position; public ReverseIterator(List<T> list) { this.list = list; this.position = list.size() - 1; } @Override public Iterator<T> iterator() { return this; } @Override public boolean hasNext() { return position >= 0; } @Override public T next() { return list.get(position--); } @Override public void remove() { throw new UnsupportedOperationException(); } } List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); for (String s : new ReverseIterator<String>(list)) { System.out.println(s); }
вы можете использовать конкретный класс
LinkedListвместо общего интерфейсаList. Тогда у вас естьdescendingIteratorдля прохода в обратном направлении.LinkedList<String > linkedList; for( Iterator<String > it = linkedList.descendingIterator(); it.hasNext(); ) { String text = it.next(); }не знаю, почему нет
descendingIteratorСArrayList...
если списки довольно малы, так что производительность не является реальной проблемой, можно использовать
reverse-методLists-классGoogle Guava. Урожайность довольноfor-each-код, и исходный список остается прежним. Кроме того, обратный список поддерживается исходным списком, поэтому любое изменение исходного списка будет отражено в обратном списке.import com.google.common.collect.Lists; [...] final List<String> myList = Lists.newArrayList("one", "two", "three"); final List<String> myReverseList = Lists.reverse(myList); System.out.println(myList); System.out.println(myReverseList); myList.add("four"); System.out.println(myList); System.out.println(myReverseList);дает следующий результат:
[one, two, three] [three, two, one] [one, two, three, four] [four, three, two, one]что означает, что обратная итерация myList может быть записана как:
for (final String someString : Lists.reverse(myList)) { //do something }
Это старый вопрос, но ему не хватает java8-дружественного ответа. Вот несколько способов обратной итерации списка с помощью Streaming API:
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 3, 3, 7, 5)); list.stream().forEach(System.out::println); // 1 3 3 7 5 int size = list.size(); ListIterator<Integer> it = list.listIterator(size); Stream.generate(it::previous).limit(size) .forEach(System.out::println); // 5 7 3 3 1 ListIterator<Integer> it2 = list.listIterator(size); Stream.iterate(it2.previous(), i -> it2.previous()).limit(size) .forEach(System.out::println); // 5 7 3 3 1 // If list is RandomAccess (i.e. an ArrayList) IntStream.range(0, size).map(i -> size - i - 1).map(list::get) .forEach(System.out::println); // 5 7 3 3 1 // If list is RandomAccess (i.e. an ArrayList), less efficient due to sorting IntStream.range(0, size).boxed().sorted(Comparator.reverseOrder()) .map(list::get).forEach(System.out::println); // 5 7 3 3 1
вот (непроверенная) реализация a
ReverseIterable. Когдаiterator()называется он создает и возвращает privateReverseIteratorреализация, которая просто отображает вызовыhasNext()доhasPrevious()и вызовыnext()сопоставляютсяprevious(). Это означает, что вы можете перебиратьArrayListв обратном порядке следующим образом:ArrayList<String> l = ... for (String s : new ReverseIterable(l)) { System.err.println(s); }Определение Класса
public class ReverseIterable<T> implements Iterable<T> { private static class ReverseIterator<T> implements Iterator { private final ListIterator<T> it; public boolean hasNext() { return it.hasPrevious(); } public T next() { return it.previous(); } public void remove() { it.remove(); } } private final ArrayList<T> l; public ReverseIterable(ArrayList<T> l) { this.l = l; } public Iterator<T> iterator() { return new ReverseIterator(l.listIterator(l.size())); } }
простой пример:
List<String> list = new ArrayList<String>(); list.add("ravi"); list.add("kant"); list.add("soni"); // Iterate to disply : result will be as --- ravi kant soni for (String name : list) { ... } //Now call this method Collections.reverse(list); // iterate and print index wise : result will be as --- soni kant ravi for (String name : list) { ... }
также нашел в коллекциях компании Google реверс метод.
есть код, который выглядит так:
List<Item> items; ... for (Item item : In.reverse(items)) { ... }поместите этот код в файл с именем "In.java":
import java.util.*; public enum In {; public static final <T> Iterable<T> reverse(final List<T> list) { return new ListReverseIterable<T>(list); } class ListReverseIterable<T> implements Iterable<T> { private final List<T> mList; public ListReverseIterable(final List<T> list) { mList = list; } public Iterator<T> iterator() { return new Iterator<T>() { final ListIterator<T> it = mList.listIterator(mList.size()); public boolean hasNext() { return it.hasPrevious(); } public T next() { return it.previous(); } public void remove() { it.remove(); } }; } } }
как было предложено по крайней мере дважды, вы можете использовать
descendingIteratorСDeque, в частностиLinkedList. Если вы хотите использовать цикл for-each (т. е. иметьIterable), вы можете построить и использовать wraper такой:import java.util.*; public class Main { public static class ReverseIterating<T> implements Iterable<T> { private final LinkedList<T> list; public ReverseIterating(LinkedList<T> list) { this.list = list; } @Override public Iterator<T> iterator() { return list.descendingIterator(); } } public static void main(String... args) { LinkedList<String> list = new LinkedList<String>(); list.add("A"); list.add("B"); list.add("C"); list.add("D"); list.add("E"); for (String s : new ReverseIterating<String>(list)) { System.out.println(s); } } }
причина: "не знаю, почему нет никакого descendingIterator с ArrayList..."
поскольку список массивов не сохраняет список в том же порядке, что и данные, добавленные в список. Поэтому никогда не используйте Arraylist .
связанный список будет хранить данные в том же порядке добавления в список.
Итак, выше в моем примере я использовал ArrayList() для того, чтобы заставить пользователя крутить свой ум и заставить их тренироваться что-то со своей стороны.
вместо это
List<String> list = new ArrayList<String>();использование:
List<String> list = new LinkedList<String>(); list.add("ravi"); list.add("kant"); list.add("soni"); // Iterate to disply : result will be as --- ravi kant soni for (String name : list) { ... } //Now call this method Collections.reverse(list); // iterate and print index wise : result will be as --- soni kant ravi for (String name : list) { ... }
Comments