如何在Java列表中获得反向列表视图?

Alb*_*ert 209 java collections reverse iterator list

我想在列表上有一个反向列表视图(以类似的方式List#sublist提供列表上的子列表视图).是否有一些提供此功能的功能?

我不想制作任何类型的列表副本,也不想修改列表.

如果我在这种情况下至少可以在列表上获得反向迭代器就足够了.


另外,我知道如何自己实现这一点.我只是问Java是否已经提供了这样的东西.

演示实施:

static <T> Iterable<T> iterableReverseList(final List<T> l) {
    return new Iterable<T>() {
        public Iterator<T> iterator() {
            return new Iterator<T>() {
                ListIterator<T> listIter = l.listIterator(l.size());                    
                public boolean hasNext() { return listIter.hasPrevious(); }
                public T next() { return listIter.previous(); }
                public void remove() { listIter.remove(); }                 
            };
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

我刚刚发现某些List实现具有descendingIterator()我需要的功能.虽然没有一般的这样的实现List.这有点奇怪,因为我看到的实现已经LinkedList足够通用了List.

jca*_*ert 209

在列表中使用.clone()方法.它将返回一个浅拷贝,这意味着它将包含指向相同对象的指针,因此您不必复制列表.然后只使用集合.

人机工程学,

Collections.reverse(list.clone());
Run Code Online (Sandbox Code Playgroud)

如果您使用的List是无权访问,clone()可以使用subList():

List<?> shallowCopy = list.subList(0, list.size());
Collections.reverse(shallowCopy);
Run Code Online (Sandbox Code Playgroud)

  • `clone()`通常会创建列表的副本.无论如何,`List#clone()`也不存在. (21认同)
  • 请注意,Collections.reverse返回void,因此您将丢失克隆引用.您需要先将克隆分配给变量,然后对其进行排序. (21认同)
  • `subList`不复制,它只提供基础列表的视图,因此反转此视图将反转基础列表. (9认同)
  • 你在技术上是正确的,List接口本身不提供clone()方法.但是ArrayList,LinkedList和Vector都可以. (6认同)
  • 我只是查看了`clone()`的实现.它确实完成了列表的完整副本(它只是没有克隆列表中的每个单个对象,但这绝不是我所说的). (2认同)

Col*_*inD 203

Guava提供了这个:Lists.reverse(List)

List<String> letters = ImmutableList.of("a", "b", "c");
List<String> reverseView = Lists.reverse(letters); 
System.out.println(reverseView); // [c, b, a]
Run Code Online (Sandbox Code Playgroud)

Collections.reverse此不同,这纯粹是一个视图 ......它不会改变原始列表中元素的顺序.此外,对于可修改的原始列表,对原始列表和视图的更改将反映在另一个列表中.

  • 问题是Guava是一个非常大的库.请参阅讨论:https://github.com/google/guava/issues/1954和https://code.google.com/p/guava-libraries/issues/detail?id=605 (10认同)
  • @Filipe de Lima Brito:ProGuard仍然是图书馆规模的最佳解决方案,尽管我们可以做出改进.在任何情况下,我都不认为库大小与此答案有任何关系. (2认同)
  • 是的,库大小与此答案无关,但与程序员有关的信息是相关的(因此,我评论过)!非常感谢这个伟大的图书馆和你的建议@ColinD! (2认同)

Sha*_*yaz 79

如果我理解正确那么它就是一行代码.它对我有用.

 Collections.reverse(yourList);
Run Code Online (Sandbox Code Playgroud)

  • 这不是列表视图.这会修改列表. (11认同)

kkr*_*ess 33

它不完全优雅,但如果你使用List.listIterator(int index),你可以在列表的末尾获得一个双向ListIterator:

//Assume List<String> foo;
ListIterator li = foo.listIterator(foo.size());

while (li.hasPrevious()) {
   String curr = li.previous()
}
Run Code Online (Sandbox Code Playgroud)


Kri*_*iya 13

Collections.reverse(nums)...它实际上颠倒了元素的顺序.下面的代码应该非常感谢 -

List<Integer> nums = new ArrayList<Integer>();
nums.add(61);
nums.add(42);
nums.add(83);
nums.add(94);
nums.add(15);
//Tosort the collections uncomment the below line
//Collections.sort(nums); 

Collections.reverse(nums);

System.out.println(nums);
Run Code Online (Sandbox Code Playgroud)

产量:15,94,83,42,61

  • 你只是在重复6年前别人写的答案 (8认同)
  • ...而不是视图。这会改变列表。 (2认同)

Boz*_*zho 7

java.util.Dequehas descendingIterator()- 如果您List是 a Deque,则可以使用它。


Mus*_*ful 7

我用这个:

public class ReversedView<E> extends AbstractList<E>{

    public static <E> List<E> of(List<E> list) {
        return new ReversedView<>(list);
    }

    private final List<E> backingList;

    private ReversedView(List<E> backingList){
        this.backingList = backingList;
    }

    @Override
    public E get(int i) {
        return backingList.get(backingList.size()-i-1);
    }

    @Override
    public int size() {
        return backingList.size();
    }

}
Run Code Online (Sandbox Code Playgroud)

像这样:

ReversedView.of(backingList) // is a fully-fledged generic (but read-only) list
Run Code Online (Sandbox Code Playgroud)


Zhe*_*lov 7

自 Java 21 以来,出现了一个新接口SequencedCollection(它是 的超级接口List)。reversed()它具有提供集合的逆序视图的方法:

jshell> List.of(1, 2, 3, 4, 5).reversed()
$1 ==> [5, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)