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/1954 및 code.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.Deque이 descendingIterator()- 당신이 경우 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.