Можно ли сделать для каждого цикла в Java в обратном порядке?

Мне нужно запустить список в обратном порядке, используя Java.

Так, где это делает это вперед:

for(String string: stringList){
//...do something
}

Есть ли способ перебрать stringList в обратном порядке, используяfor each синтаксис?

Для ясности: я знаю, как перебирать список в обратном порядке, но хотел бы знать (ради любопытства), как это сделать вfor each стиль.

 muusbolla08 июл. 2009 г., 15:46
Точка «для каждого» Цикл заключается в том, что вам просто нужно выполнить операцию над каждым элементом, а порядок не важен. For-each может обрабатывать элементы в совершенно случайном порядке, и он все равно будет делать то, для чего он предназначен. Если вам нужно обработать элементы определенным образом, я бы предложил сделать это вручную.
 Tom Hawtin - tackline08 июл. 2009 г., 15:50
Библиотека коллекций Java. На самом деле не имеет ничего общего с языком. Виноват Джош Блох.
 skaffman08 июл. 2009 г., 15:37
Как ни странно, я частично прочитал этот вопрос, прочитав раздел книги Scala, посвященный операциям с неизменяемым списком ... прекрасная демонстрация отсутствия выразительной силы в Java.
 robert13 авг. 2014 г., 10:58
@muusbolla, это не правда. Может быть, в случаеSet производные коллекции.foreach гарантирует итерацию в порядке итератора, возвращаемого изiterator() Метод сбора.docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
 Lee Kowalkowski22 мар. 2011 г., 15:56
@muusbolla: Но как список являетсяordered Коллекция, конечно же, ее порядок будет соблюден, независимо от? Поэтому for-each не будет обрабатывать элементы списка в случайном порядке.

Ответы на вопрос(12)

который даст вам перечислитель, который обратит элементы за вас.

Вы должны быть в состоянии сделать это в Java, создав собственную реализацию Iterable, которая будет возвращать элементы в обратном порядке.

Затем вы должны создать экземпляр оболочки (или вызвать метод what-have-you), который вернет реализацию Iterable, которая переворачивает элемент в каждом цикле.

приведенные выше, только удовлетворяют требованию, либо заключая в оболочку другой метод, либо вызывая внешний код;

Вот решение, скопированное изThinking in Java 4th editionГлава 11.13.1AdapterMethodIdiom;

Вот код:

// 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
*///:~
 14 мар. 2017 г., 12:18
почемуint current = size() - 1 право? почему неint current = this.size() - 1 или жеint current = super.size() - 1

если вы хотите использовать для каждого синтаксиса «из коробки» и перейти в обратном порядке.

Решение Вопроса

он фактически переворачивает исходный список на месте. Если вы используете это:

Неправильный способ!

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);
}
 13 авг. 2009 г., 11:45
Благодарю. Я исправил это.
 09 мая 2012 г., 21:42
Collections.reverse () НЕ возвращает обратную копию, но действует в списке, передаваемом ему в качестве параметра. Как и ваше решение с итератором, хотя. Действительно элегантный
 08 июл. 2009 г., 15:50
Это в основном то, что делает Google Iterables.reverse, да :)
 Ron Tuffin08 июл. 2009 г., 16:21
Я знаю, что есть «правило» что мы должны принять ответ Джона :), но ... я хочу принять этот (даже если они по сути одинаковы), потому что он не требует, чтобы я включил другую стороннюю библиотеку (хотя некоторые могут утверждать, что по этой причине нарушает одно из главных преимуществ ОО - возможность многократного использования).
 13 авг. 2009 г., 11:43
Небольшая ошибка: в public void remove () не должно быть оператора return, это должно быть просто: i.remove ();

Кроме того, вы не хотите выполнять реверс каждый раз, когда делаете цикл - будет ли это так, если один изIterables.reverse ideas был применен?

Collections.reverse(stringList);

for(String string: stringList){
//...do something
}

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html перевернуть список, затем зациклить.

ю, и ее повторение сохраняет порядок по контракту. Я ожидал, что стек будет повторяться в обратном порядке, но, к сожалению, это не так. Итак, самое простое решение, о котором я могу подумать, это:

for (int i = stack.size() - 1; i >= 0; i--) {
    System.out.println(stack.get(i));
,}

Я понимаю, что это не "для каждого" решение петли. Я скорее использую цикл for, чем представляю новую библиотеку, такую как Google Collections.

Collections.reverse () также выполняет эту работу, но обновляет список, а не возвращает копию в обратном порядке.

 20 мая 2011 г., 19:54
 21 мая 2011 г., 04:51
Кроме того, он отклоняется от запроса в OP, который явно запрашиваетfor each синтаксис

комментарий: Вы должны быть в состоянии использовать Apache CommonsReverseListIterator

Iterable<String> reverse 
    = new IteratorIterable(new ReverseListIterator(stringList));

for(String string: reverse ){
    //...do something
}

Как@rogerdpack сказалнужно обернутьReverseListIterator какIterable.

что есть лучший способ начать с последнего элемента, чем цикл while до конца.

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);           
    }
}

ной библиотеки, которая поддерживает синтаксис for-each, который уже является синтаксическим сахаром, который они внесли в язык позднее.

Вы можете сделать что-то вроде для (Элемент Item: myList.clone (). Reverse ()) и заплатить соответствующую цену.

Это также вполне согласуется с явным явлением, заключающимся в отсутствии удобных способов выполнения дорогостоящих операций - поскольку список по определению может иметь O (N) сложность произвольного доступа (вы могли бы реализовать интерфейс с одной линией), наоборот итерация может в конечном итоге быть O (N ^ 2). Конечно, если у вас есть ArrayList, вы не платите эту цену.

 08 июл. 2009 г., 15:52
Вы можете запустить ListIterator в обратном направлении, который может быть заключен в итератор.
 28 апр. 2010 г., 00:40
У Deque есть обратный итератор.
 08 июл. 2009 г., 16:01
@ Том: Хороший вопрос. Тем не менее, с помощью итератора вы все еще делаете надоедливый цикл в старом стиле, и вы все равно можете заплатить стоимость, чтобы добраться до последнего элемента для начала ... Я добавил квалификатор в свой ответ, хотя, спасибо.

ся использование 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 идет на& quot; Способы перебора списка в Java & quot;

Google Guava Library:

for (String item : Lists.reverse(stringList))
{
    // ...
}

Обратите внимание, чтоLists.reverse doesn't перевернуть всю коллекцию или сделать что-нибудь подобное - она просто позволяет выполнять итерацию и произвольный доступ в обратном порядке. Это более эффективно, чем сначала поменять коллекцию.

Чтобы отменить произвольную итерацию, вам нужно все это прочитать, а затем «повторить». это задом наперед.

(Если вы его еще не используете, яthoroughly рекомендую взглянуть нагуайява, Это отличный материал.)

 08 июл. 2009 г., 15:55
Интересно, почему Джакарта никогда не удосужилась обновить Apache Commons.
 18 окт. 2011 г., 16:54
Iterables.reverse устарел, используйте взамен Lists.reverse или ImmutableList.reverse.
 08 июл. 2009 г., 15:56
Они обновили его, это то, что я говорю. Они просто не выпустили его.
 08 июл. 2009 г., 15:47
Мне это нравится. Если бы это не было так полезно, я бы назвал это штепселем.
 08 июл. 2009 г., 15:44
Наша кодовая база интенсивно использует обобщенную версию коллекций Commons, выпущенную larvalabs (larvalabs.com/collections). Просматривая репозиторий SVN для Apache Commons, становится ясно, что большая часть работы по выпуску java 5-версии Commons Collections выполнена, они просто еще не выпустили ее.

Ваш ответ на вопрос