这里的诀窍是定义“反向”。可以就地修改列表,以相反的顺序创建副本,或以相反的顺序创建视图。
直观地说,最简单的方法是Collections.reverse
:
Collections.reverse(myList);
这个方法修改了列表。也就是说,Collections.reverse
获取列表并覆盖其元素,不留下任何未反转的副本。这适用于某些用例,但不适用于其他用例;此外,它假定列表是可修改的。如果这是可以接受的,我们很好。
如果没有,可以按相反的顺序创建副本:
static <T> List<T> reverse(final List<T> list) {
final List<T> result = new ArrayList<>(list);
Collections.reverse(result);
return result;
}
这种方法有效,但需要对列表进行两次迭代。复制构造函数 ( new ArrayList<>(list)
) 迭代列表, 也是如此Collections.reverse
。如果我们愿意的话,我们可以重写这个方法只迭代一次:
static <T> List<T> reverse(final List<T> list) {
final int size = list.size();
final int last = size - 1;
// create a new list, with exactly enough initial capacity to hold the (reversed) list
final List<T> result = new ArrayList<>(size);
// iterate through the list in reverse order and append to the result
for (int i = last; i >= 0; --i) {
final T element = list.get(i);
result.add(element);
}
// result now holds a reversed copy of the original list
return result;
}
这更有效,但也更冗长。
或者,我们可以重写上面的代码以使用 Java 8 的stream
API,有些人认为它比上面的更简洁易读:
static <T> List<T> reverse(final List<T> list) {
final int last = list.size() - 1;
return IntStream.rangeClosed(0, last) // a stream of all valid indexes into the list
.map(i -> (last - i)) // reverse order
.mapToObj(list::get) // map each index to a list element
.collect(Collectors.toList()); // wrap them up in a list
}
注意。这Collectors.toList()
对结果列表几乎没有保证。如果要确保结果以 ArrayList 的形式返回,请Collectors.toCollection(ArrayList::new)
改用。
第三个选项是以相反的顺序创建视图。这是一个更复杂的解决方案,值得进一步阅读/它自己的问题。Guava 的Lists#reverse方法是一个可行的起点。
选择一个“最简单”的实现留给读者作为练习。