Идиоматический способ использования для каждого цикла с заданным итератором?

Кажется, что под давлением nginx попытался вытащить angular.js из своего кэша и не смог из-за проблем с разрешениями. Вот что решило эту проблему:

root@amac-2:/usr/local/var/run/nginx $ chown -R _www:admin proxy_temp

_www:admin может отличаться в вашем случае, в зависимости от того, какой пользователь владеет процессом nginx. Дополнительная информация о ServerFault:

https://serverfault.com/questions/534497/why-do-nginx-process-run-with-user-nobody

32
задан Mark Peters 7 October 2010 в 15:46
поделиться

5 ответов

Что я, вероятно, сделал бы, так это просто сделал бы вспомогательный класс под названием Deques, который мог бы поддерживать это, наряду с другими утилитами, если это необходимо.

public class Deques {
  private Deques() {}

  public static <T> Iterable<T> asDescendingIterable(final Deque<T> deque) {
    return new Iterable<T>() {
      public Iterator<T> iterator() {
        return deque.descendingIterator();
      }
    }
  }
}

Это еще один случай, когда очень жаль, что у нас еще нет лямбд и ссылок на методы. В Java 8 вы сможете написать что-то вроде этого, учитывая, что ссылка на метод descendingIterator() соответствует сигнатуре Iterable:

Deque<String> deque = ...
for (String s : deque::descendingIterator) { ... }
16
ответ дан 27 November 2019 в 20:28
поделиться

Вместо того, чтобы создавать descendingIterator, было бы лучше написать метод descendingIterable(), чтобы он возвращал итерацию по убыванию, основанную на деке, который в основном занимает место вашего анонимного класса. Это кажется довольно разумным для меня. Согласно предложению Колина, итеративная реализация, возвращаемая этим методом, будет вызывать descendingIterator в исходной деке каждый раз, когда вызывается ее собственный метод iterator().

Если у вас только есть итератор и вы хотите сохранить его таким образом, вам нужно написать реализацию Iterable<T>, которая обернет итератор и вернет его ровно один раз , выбрасывая исключение, если iterator() вызывается более одного раза. Это сработало бы, но было бы довольно уродливо.

9
ответ дан 27 November 2019 в 20:28
поделиться
public class DescendingIterableDequeAdapter<T> implements Iterable<T> {
    private Deque<T> original;

    public DescendingIterableDequeAdapter(Deque<T> original) {
        this.original = original;
    }

    public Iterator<T> iterator() {
         return original.descendingIterator();
    }
}

А затем

for (T item : new DescendingIterableDequeAdapter(deque)) {

}

Итак, для каждого такого случая вам понадобится специальный адаптер. Я не думаю, что теоретически возможно делать то, что вы хотите, потому что объект должен знать, какие существуют методы, возвращающие итераторы, чтобы он мог их вызывать.

Что касается вашего дополнительного вопроса - я полагаю, потому что цикл for-each действительно должен был сделать вещи короче для сценариев общего назначения. А вызов дополнительного метода делает синтаксис более многословным. Он мог бы поддерживать Iterable и Iterator, но что, если переданный объект реализовал оба? (было бы странно, но все же возможно).

3
ответ дан 27 November 2019 в 20:28
поделиться

У Guava, конечно, есть решение для обратного повторяемого сценария, но, к сожалению, вам нужно два шага. Iterables.reverse () принимает List в качестве параметра, а не Iterable.

final Iterable<String> it = Arrays.asList("a", "b", "c");
for(final String item : Iterables.reverse(Lists.newArrayList(it))){
    System.out.println(item);
}

Вывод:

c
b
a

1
ответ дан 27 November 2019 в 20:28
поделиться

Apache Commons Collections API имеет класс под названием IteratorIterable , чтобы сделать именно это:

Iterator<X> iter;
for (X item : new IteratorIterable(iter)) {
    ...
}
0
ответ дан 27 November 2019 в 20:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: