use*_*999 4 java linked-list arraylist java-8
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());
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)averse: Hello 2 Chocolate 10 reverse: 10 Chocolate 2 Hello
但是descendingIterator不适用于List和ArrayList.有没有在列表说明任何解决办法,或者为什么的descendingIterator缺席的名单?
问题类似于可以为java中的每个循环以相反的顺序执行吗?.但所有答案都建议使用临时解决方案或第三方库.
可能有使用溪流可能吗?(不幸的是,我的谷歌搜索只给出了流Java 8流逆序的缺失标准反转)
正如我所提到的,我的问题与关于流的问题有关,但是:
没有一个很好的理由为什么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(); }
};
};
}
Run Code Online (Sandbox Code Playgroud)
您可以使用它来实现您的示例:
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
Run Code Online (Sandbox Code Playgroud)
或者你可以在增强型for循环中使用它:
for (String s : descendingIterable(list)) {
System.out.println(s);
}
10
Chocolate
2
Hello
Run Code Online (Sandbox Code Playgroud)
我最初创建了一个Iterator而不是一个Iterable,但后者更有用,因为它可以在增强型for循环中使用.
还要注意,这里有一个小皱纹,即如果List可以同时修改则存在竞争条件.这发生在这里的代码:
list.listIterator(list.size())
Run Code Online (Sandbox Code Playgroud)
如果有可能,您必须在列表中使用外部同步,或者如果列表是a CopyOnWriteArrayList,则必须先克隆它.有关后者的更多信息,请参阅此答案.
有没有关于为什么List 中没有DescendingIterator 的解释?
迭代列表的效率高度依赖于该列表的实现。
在设计接口时,您通常希望该接口适合其任何可能的实现。
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);
Run Code Online (Sandbox Code Playgroud)