Java의 목록에서 목록을 반대로 보는 방법은 무엇입니까?


214

목록에서 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.


1
목록을 역순으로 작성하여 시작할 수 있습니까?
Tony Ennis

그렇습니다-java.uitl.List.listIterator (int) download.oracle.com/javase/6/docs/api/java/util/…
TofuBeer

이 링크를 방문하여 목록을 뒤집는 방법을 찾는 답을 찾으면 다음과 같습니다.Collections.reverse(list)
ZhaoGang

답변:


210

구아바 는 이것을 제공합니다 : 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, 이것은 순전히 보기입니다 ... 원래 목록의 요소 순서를 변경하지 않습니다. 또한 수정 가능한 원본 목록을 사용하면 원본 목록과보기 모두에 대한 변경 내용이 다른쪽에 반영됩니다.


11
문제는 구아바가 매우 큰 도서관이라는 것입니다. 토론 참조 : github.com/google/guava/issues/1954code.google.com/p/guava-libraries/issues/detail?id=605
Filipe Brito

2
@Filipe de Lima Brito : ProGuard는 여전히 라이브러리 크기에 가장 적합한 솔루션이지만 개선 할 가능성이 있습니다. 어쨌든 라이브러리 크기 가이 답변과 어떤 관련이 있다고 생각하지 않습니다.
ColinD

2
예, 라이브러리 크기는이 답변과 관련이 없지만 프로그래머에게 알리는 것과 관련이 있습니다 (따라서 주석을 달았습니다)! 이 훌륭한 도서관과 여러분의 제안 @ColinD에 대단히 감사합니다!
Filipe Brito

@ ColinD, p, 내 실수였다. 동료가 네임 스페이스 및 클래스 ( List) 는 동일 하지만 역 방법이없는 Google 컬렉션을 추가했습니다 . 그것을 제거하면 구아바를 다시 사용할 수있게되었습니다.
AaA

개발자는 항상 어떤 라이브러리를 사용할 수 있는지 제어 할 수 없으며, 아주 간단한 무언가를 위해 완전히 새로운 라이브러리를 추가하는 것은 과도한 문제처럼 보입니다. 특히 문제를 해결할 수 있다는 점에서ListIterator.previous()
Jonathan Benn

218

List에서 .clone () 메소드를 사용하십시오. 얕은 복사본을 반환하므로 동일한 개체에 대한 포인터가 포함되므로 목록을 복사 할 필요가 없습니다. 그런 다음 컬렉션을 사용하십시오.

에르고,

Collections.reverse(list.clone());

를 사용하고 List있고 액세스 clone()할 수없는 경우 subList()다음을 사용할 수 있습니다 .

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

21
clone()일반적으로 목록의 복사본을 만듭니다. 어쨌든 List#clone()존재하지 않습니다.
Albert Albert

6
당신은 기술적으로 맞습니다. List 인터페이스 자체는 clone () 메소드를 제공하지 않습니다. 그러나 ArrayList, LinkedList 및 Vector는 모두 수행합니다.
jcalvert

2
방금 구현을 찾았습니다 clone(). 실제로 목록의 전체 사본을 수행합니다 (목록의 각 단일 객체 만 복제하지는 않지만 결코 내가 말한 것은 아닙니다).
Albert

21
Collections.reverse는 void를 반환하므로 복제 참조를 잃게됩니다. 먼저 클론을 변수에 할당 한 다음 정렬해야합니다.
user12722

10
subList복사하지 않고 기본 목록에 대한보기 만 제공 하므로이보기를 되 돌리면 기본 목록을 뒤집습니다.
Roland

80

내가 올바른 것으로 이해했다면 그것은 한 줄의 코드입니다.

 Collections.reverse(yourList);

12
그것은 목록보기가 아닙니다. 목록을 수정합니다.
Albert

35

정확히 우아하지는 않지만 List.listIterator (int index)를 사용하면 목록 끝까지 양방향 ListIterator를 얻을 수 있습니다.

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

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

1
이것은 (1) 도서관이 필요하지 않고 (2) OP가 요청한대로 원래 목록을 수정하지 않기 때문에 가장 좋은 대답입니다.
Jonathan Benn

12

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


8
6 년 전에 다른 사람이 작성한 답변을 반복하고 있습니다.
Jonathan Benn

1
...보기가 아닙니다. 이것은 목록을 변경합니다.
Jason S

6

java.util.DequedescendingIterator()- 당신이 경우 List이다 Deque, 당신이 사용할 수 있습니다.


내장 descndingIterator () 메소드를 사용하지 않으려면 ConcurrentLinkedDeque를 사용하는 것이 매우 큰 목록을 뒤집는 것이 가장 좋을 것 같습니다. 기본적으로 설문 조사를 사용하여 한 갑판에서 새로운 갑판으로 복사 한 다음 제공합니까? 일종의 카드 한 벌을 가지고 맨 위를 새 더미로 가져가는 것과 같습니다.
djangofan

4

나는 이것이 오래된 게시물이라는 것을 알고 있지만 오늘 나는 이와 같은 것을 찾고있었습니다. 결국 코드를 ​​직접 작성했습니다.

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 개를 넘지 않습니다).

누군가에게 도움이되기를 바랍니다.


2
코드에는 한 가지 문제가 있습니다. List를 넣을 수는 있지만 항상 ArrayList를 List로 반환합니다. LinkedList가 필요한 경우 어떻게해야합니까? myList를 수정하고 void를 리턴하는 것이 좋습니다.
Dmitry Zaytsev

2
이것은 실제로 내가 요구 한 것이 아닙니다. 사본이 아닌 일종의 프록시 /보기를 요청했습니다.
Albert

4

나는 이것을 사용한다 :

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

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

5
그것은 목록보기가 아닙니다. 보기는 사본의 반대입니다.
Albert

빈 목록의 반대 목록이 null입니까?
ShellFish 2016 년

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

-3

수업 reverse(...)방법을 사용하십시오 java.util.Collections. 목록을 매개 변수로 전달하면 목록이 반전됩니다.

Collections.reverse(list);

1
기존 답변의 사본
Karl Richter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.