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

问题描述 投票:0回答:13

我想在列表上有一个反向列表视图(与

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(); }                 
            };
        }
    };
}

我刚刚发现一些

List
实现具有
descendingIterator()
这正是我所需要的。尽管
List
没有通用的此类实现。这有点奇怪,因为我在
LinkedList
中看到的实现足够通用,可以与任何
List
一起使用。

java list collections iterator reverse
13个回答
243
投票

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

因此,

Collections.reverse(list.clone());

如果您使用的是

List
并且无权访问
clone()
,您可以使用
subList()
:

List<?> shallowCopy = list.subList(0, list.size());
Collections.reverse(shallowCopy);

238
投票

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]

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


85
投票

如果我理解正确,那么它只是一行代码。它对我有用。

 Collections.reverse(yourList);

46
投票

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

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

while (li.hasPrevious()) {
   String curr = li.previous();
}

10
投票

我用这个:

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();
    }

}

像这样:

ReversedView.of(backingList) // is a fully-fledged generic (but read-only) list

8
投票

java.util.Deque
descendingIterator()
- 如果您的
List
Deque
,您可以使用它。


8
投票

自 Java 21 起,出现了一个新接口

SequencedCollection
(这是
List
的超级接口)。它有方法
reversed()
提供集合的逆序视图:

jshell> List.of(1, 2, 3, 4, 5).reversed()
$1 ==> [5, 4, 3, 2, 1]

7
投票

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);

输出:15,94,83,42,61


3
投票

我知道这是一篇旧帖子,但今天我正在寻找类似的东西。最后我自己写了代码:

private List reverseList(List myList) {
    List invertedList = new ArrayList();
    for (int i = myList.size() - 1; i >= 0; i--) {
        invertedList.add(myList.get(i));
    }
    return invertedList;
}

不建议用于长列表,这根本没有优化。对于受控场景来说,这是一种简单的解决方案(我处理的列表不超过 100 个元素)。

希望它对某人有帮助。


1
投票

您还可以在请求对象时反转位置:

Object obj = list.get(list.size() - 1 - position);

1
投票

对于小型列表,我们可以创建

LinkedList
,然后可以使用降序迭代器:

List<String> stringList = new ArrayList<>(Arrays.asList("One", "Two", "Three"));
stringList.stream().collect(Collectors.toCollection(LinkedList::new))
         .descendingIterator().
         forEachRemaining(System.out::println); // Three, Two, One
System.out.println(stringList); // One, Two, Three

0
投票

对于任何...

  1. 不想修改列表
  2. 不想使用像Guava这样的第三方库
  3. 想要一个不可修改的列表
  4. 想要一个遵循 Collection API 流畅调用风格的函数
  5. 想要看到现代风格的代码(而不是 20 世纪 90 年代末非常类似 C 的代码)

...这是一个有用的解决方案:

/**
 * Reverse the order of the instances returning an unmodifiable list.
 *
 * @param list the list to copy from while reversing
 * @param <T> the type of instances contained in the list
 * @return an unmodifiable list with the contained instances in reverse order
 */
public static <T> List<T> reverse(List<T> list) {
  if (list.size() > 1) {
    var size = list.size();

    return IntStream.range(0, size)
        .mapToObj(index -> list.get(size - 1 - index))
        .toList();
  } else if (list.size() == 1) {
    return list;
  }

  return List.of();
}

-1
投票

您也可以这样做:

static ArrayList<String> reverseReturn(ArrayList<String> alist)
{
   if(alist==null || alist.isEmpty())
   { 
       return null;
   }

   ArrayList<String> rlist = new ArrayList<>(alist);

   Collections.reverse(rlist);
   return rlist;
}
© www.soinside.com 2019 - 2024. All rights reserved.