这里的诀窍在于如何定义“反向”。可以就地修改列表,以相反的顺序创建副本,或以相反的顺序创建视图。
直观地说,最简单的方法是Collections.reverse:
Collections.reverse(myList);
此方法将就地修改列表。那就是集合。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的流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
}
nb。collections . tolist()对结果列表的保证很少。如果你想确保返回的结果是一个数组列表,请使用collections . tocollection (ArrayList::new)。
第三个选项是以相反的顺序创建视图。这是一个更复杂的解决方案,值得进一步阅读/它本身的问题。Guava的Lists#反向方法是一个可行的起点。
选择“最简单”的实现留给读者练习。