LinkedList 可以使用升序或降序迭代器进行迭代:
LinkedList<Object> list = new LinkedList<Object>();
...
StringJoiner sJ1 = new StringJoiner(" ");
list.iterator().forEachRemaining(a -> sJ1.add(a.toString()));
System.out.println("averse: \n" + sJ1.toString());
StringJoiner sJ2 = new StringJoiner(" ");
list.descendingIterator().forEachRemaining(a -> sJ2.add(a.toString()));
System.out.println("reverse: \n" + sJ2.toString());
averse: Hello 2 Chocolate 10 reverse: 10 Chocolate 2 Hello
但 listndingIterator 不适用于 List 和 ArrayList 。 是否有任何变通方法或列表说明,为什么 list 中 descendingIterator 不存在?
问题类似于Can one do a for each loop in java in reverse order?。但所有答案都建议使用临时解决方案或第三方库。
可能有可能使用流媒体流吗? (不幸的是,我的Google搜索仅为流Java 8 stream reverse order提供了标准反转)
正如我所提到的,我的问题与流有关,但是:
答案 0 :(得分:5)
没有一个很好的理由说明List
无法使用降序迭代器。每个List
都需要支持ListIterator
,hasPrevious()
可以使用previous()
和Iterable
方法以相反的顺序进行迭代。不过,这似乎是一个相当罕见的用例。
这是一个小实用程序方法,它以相反的顺序将ListIterator
调整为static <T> Iterable<T> descendingIterable(List<? extends T> list) {
return () -> {
ListIterator<? extends T> li = list.listIterator(list.size());
return new Iterator<T>() {
public boolean hasNext() { return li.hasPrevious(); }
public T next() { return li.previous(); }
};
};
}
迭代:
List<String> list = Arrays.asList("Hello", "2", "Chocolate", "10");
StringJoiner sj = new StringJoiner(" ");
descendingIterable(list).iterator().forEachRemaining(sj::add);
System.out.println(sj);
10 Chocolate 2 Hello
您可以使用它来实现您的示例:
for (String s : descendingIterable(list)) {
System.out.println(s);
}
10
Chocolate
2
Hello
或者您可以在增强型for循环中使用它:
Iterator
我最初创建了一个Iterable
而不是List
,但后者更有用,因为它可以在增强型for循环中使用。
另请注意,如果可以同时修改 list.listIterator(list.size())
,则会出现一个小的皱纹。这发生在这里的代码:
CopyOnWriteArrayList
如果有可能,您必须在列表中使用外部同步,或者如果列表是complex_stuff = None
def load_complex_stuff():
global complex_stuff
if complex_stuff is None:
import complex_stuff
def func_using_it():
load_complex_stuff()
... more ...
def func_using_it_2():
load_complex_stuff()
... more ...
,则必须先克隆它。有关后者的更多信息,请参阅this answer。
答案 1 :(得分:4)
是否解释为什么列表中没有 descendingIterator ?
迭代List的效率在很大程度上取决于该列表的实现 在设计界面时,您通常希望界面适合于任何可能的实现。
Java链接列表是双重链接列表,这意味着每个元素都链接到它之前和之后的元素,因此可以编写有效的升序和降序迭代器。
如果您使用单个链接列表,那么迭代迭代它会非常低效,您需要遍历整个列表,直到每次迭代的当前索引。
我怀疑是出于这个原因,语言设计者决定从List接口中省略一个降序迭代器。
使用基于索引的方法可以相当容易地实现高效的ArrayList降序迭代器,在LinkedList上使用索引方法将比其首选实现慢得多。
下行迭代方法的一些示例:
for(int i=list.size() -1; i >= 0; i--){
System.out.println(list.get(i));
}
IntStream.range(0, list.size())
.map(i-> list.size() - 1 - i)
.mapToObj(list::get)
.forEach(System.out::println);
答案 2 :(得分:1)
我在这里看到两种可能的解决方案:
使用Intstream创建以相反顺序遍历列表的流:
IntStream.range(0, list.length())
.mapToObj(i -> list.get(list.length() - i - 1)
.forEach(...);
反转列表本身(如果您无法修改原始列表,则创建副本)
List<String> reversed = new ArrayList(list);
Collections.reverse(reversed);
reversed.stream()
.forEach(...)