Можно ли сделать для каждого цикла в java в обратном порядке?
Мне нужно запустить список в обратном порядке с помощью Java.
Итак, где это делает его вперед:
for(String string: stringList){
//...do something
}
есть ли способ повторить список строк в обратном порядке с помощью для каждого синтаксис?
для ясности: я знаю, как перебирать список в обратном порядке, но хотел бы знать (ради любопытства), как это сделать в для каждого стиль.
12 ответов:
не используйте коллекции.обратный метод он фактически отменяет исходный список на месте. Если вы используете его:
неправильный путь!
Collections.reverse(new ArrayList(stringList))
чтобы избежать изменения оригинала, это возвращает новый список с элементами исходного списка, скопированными в него в обратном порядке, и такой имеет o(n) требования к производительности и пространству в отношении размера исходного списка.
В качестве более эффективного решения вы можете написать класс, который представляет собой перевернутое представление списка как итеративного универсального. Итератор, возвращаемый вашим классом, будет использовать ListIterator украшенного списка для обхода элементов в обратном порядке.
например:
public class Reversed<T> implements Iterable<T> { private final List<T> original; public Reversed(List<T> original) { this.original = original; } public Iterator<T> iterator() { final ListIterator<T> i = original.listIterator(original.size()); return new Iterator<T>() { public boolean hasNext() { return i.hasPrevious(); } public T next() { return i.previous(); } public void remove() { i.remove(); } }; } public static <T> Reversed<T> reversed(List<T> original) { return new Reversed<T>(original); } }
а вы бы использовать его как:
import static Reversed.reversed; ... List<String> someStrings = getSomeStrings(); for (String s : reversed(someStrings)) { doSomethingWith(s); }
для списка, вы можете использовать Библиотека Google Guava:
for (String item : Lists.reverse(stringList)) { // ... }
отметим, что
Lists.reverse
не отменить всю коллекцию, или сделать что - нибудь подобное-это просто позволяет итерации и произвольный доступ, в обратном порядке. Это более эффективно, чем сначала отменить сбор.чтобы отменить произвольную итерацию, вам нужно будет прочитать все это, а затем "воспроизвести" его назад.
(Если вы еще не используя его, я бы тщательно рекомендуем вам взглянуть на гуавы. Это отличный материал.)
список (в отличие от набора) является упорядоченной коллекцией, и итерация по нему сохраняет порядок по контракту. Я ожидал стек, чтобы выполнить итерации в обратном порядке, но, к сожалению, это не так. Поэтому самое простое решение я могу думать, это:
for (int i = stack.size() - 1; i >= 0; i--) { System.out.println(stack.get(i)); }
Я понимаю, что это не "для каждого" цикла решения. Я бы предпочел использовать цикл for, чем вводить новую библиотеку, такую как коллекции Google.
сборники.обратный () также делает работу, но это обновляет список, а не возвращает копию в обратном порядке.
это будет беспорядок с исходным списком, а также должен быть вызван вне цикла. Также вы не хотите выполнить обратный каждый раз, когда вы цикл - это было бы верно, если один из ?
Collections.reverse(stringList); for(String string: stringList){ //...do something }
AFAIK в стандартной библиотеке нет стандартного типа "reverse_iterator", который поддерживает синтаксис for-each, который уже является синтаксическим сахаром, который они принесли в конце языка.
вы могли бы сделать что-то вроде for(Item element: myList.клон.)(обратный ()) и оплатить соответствующую цену.
Это также кажется довольно совместимым с очевидным явлением не давая вам удобные способы делать дорогие операции - так как список, по определению, может иметь O (N) сложность произвольного доступа(вы можете реализовать интерфейс с одной связью), обратная итерация может оказаться O (N^2). Конечно, если у вас есть ArrayList, вы не платите эту цену.
Это может быть вариантом. Надеюсь, что есть лучший способ начать с последнего элемента, чем в то время как цикл до конца.
public static void main(String[] args) { List<String> a = new ArrayList<String>(); a.add("1");a.add("2");a.add("3");a.add("4");a.add("5"); ListIterator<String> aIter=a.listIterator(); while(aIter.hasNext()) aIter.next(); for (;aIter.hasPrevious();) { String aVal = aIter.previous(); System.out.println(aVal); } }
по состоянию на комментарий: вы должны быть в состоянии использовать Apache Commons На
ReverseListIterator
Iterable<String> reverse = new IteratorIterable(new ReverseListIterator(stringList)); for(String string: reverse ){ //...do something }
как @rogerdpack сказал, вам необходимо заключить в
ReverseListIterator
какIterable
.
Не без написания некоторого пользовательского кода, который даст вам перечислитель, который перевернет элементы для вас.
вы должны быть в состоянии сделать это в Java, создав пользовательскую реализацию Iterable, которая будет возвращать элементы в обратном порядке.
затем вы создадите экземпляр оболочки (или вызовите метод, что у вас есть), который вернет итерационную реализацию, которая отменяет элемент в каждом цикле.
вы можете использовать класс коллекцийhttp://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html чтобы изменить список, то цикл.
вам нужно изменить ваш набор, если вы хотите использовать для каждого синтаксиса из коробки и идут в обратном порядке.
все ответы выше только выполняют требование, либо путем обертывания другого метода или вызова некоторого внешнего кода снаружи;
вот решение скопировано с мышление в Java 4-е издание глава 11.13.1 AdapterMethodIdiom;
вот код:
// The "Adapter Method" idiom allows you to use foreach // with additional kinds of Iterables. package holding; import java.util.*; @SuppressWarnings("serial") class ReversibleArrayList<T> extends ArrayList<T> { public ReversibleArrayList(Collection<T> c) { super(c); } public Iterable<T> reversed() { return new Iterable<T>() { public Iterator<T> iterator() { return new Iterator<T>() { int current = size() - 1; //why this.size() or super.size() wrong? public boolean hasNext() { return current > -1; } public T next() { return get(current--); } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; } }; } } public class AdapterMethodIdiom { public static void main(String[] args) { ReversibleArrayList<String> ral = new ReversibleArrayList<String>( Arrays.asList("To be or not to be".split(" "))); // Grabs the ordinary iterator via iterator(): for(String s : ral) System.out.print(s + " "); System.out.println(); // Hand it the Iterable of your choice for(String s : ral.reversed()) System.out.print(s + " "); } } /* Output: To be or not to be be to not or be To *///:~
определенно поздний ответ на этот вопрос. Одна возможность-использовать ListIterator в цикле for. Это не так чисто, как двоеточие-синтаксис, но он работает.
List<String> exampleList = new ArrayList<>(); exampleList.add("One"); exampleList.add("Two"); exampleList.add("Three"); //Forward iteration for (String currentString : exampleList) { System.out.println(currentString); } //Reverse iteration for (ListIterator<String> itr = exampleList.listIterator(exampleList.size()); itr.hasPrevious(); /*no-op*/ ) { String currentString = itr.previous(); System.out.println(currentString); }
кредит для синтаксиса ListIterator идет в "способы перебора списка в Java"