Bagaimana cara mendapatkan tampilan daftar terbalik pada daftar di Jawa?

214

Saya ingin memiliki tampilan daftar terbalik pada daftar (dengan cara yang sama daripada List#sublistmemberikan tampilan sublist pada daftar). Apakah ada beberapa fungsi yang menyediakan fungsi ini?

Saya tidak ingin membuat salinan apa pun dari daftar atau memodifikasi daftar.

Akan cukup jika saya bisa mendapatkan setidaknya iterator terbalik pada daftar dalam kasus ini.


Juga, saya tahu cara mengimplementasikan ini sendiri. Saya hanya bertanya apakah Java sudah menyediakan sesuatu seperti ini.

Implementasi demo:

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

Saya baru tahu bahwa beberapa Listimplementasi memiliki descendingIterator()apa yang saya butuhkan. Meskipun tidak ada implementasi seperti umum untuk List. Yang agak aneh karena implementasi yang saya lihat di LinkedListcukup umum untuk bekerja dengan siapa pun List.

Albert
sumber
1
Bisakah Anda membuat daftar dengan urutan terbalik?
Tony Ennis
Ya itu - java.uitl.List.listIterator (int) download.oracle.com/javase/6/docs/api/java/util/...
TofuBeer
Jika Anda mengunjungi tautan ini untuk menemukan jawaban cara membalikkan (memodifikasi) daftar, ini jawabannya:Collections.reverse(list)
ZhaoGang

Jawaban:

209

Guava menyediakan ini: Lists.reverse (Daftar)

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

Tidak seperti Collections.reverseini, ini murni pemandangan ... itu tidak mengubah urutan elemen dalam daftar asli. Selain itu, dengan daftar asli yang dapat dimodifikasi, perubahan pada daftar asli dan tampilan tercermin dalam yang lain.

ColinD
sumber
11
Masalahnya adalah bahwa Guava adalah perpustakaan yang sangat besar. Lihat diskusi: github.com/google/guava/issues/1954 dan code.google.com/p/guava-libraries/issues/detail?id=605
Filipe Brito
2
@Filipe de Lima Brito: ProGuard masih merupakan solusi terbaik untuk ukuran perpustakaan, meskipun ada kemungkinan perbaikan yang dapat kami lakukan. Bagaimanapun, saya tidak berpikir ukuran perpustakaan relevan dengan cara apa pun untuk jawaban ini.
ColinD
2
Ya, ukuran perpustakaan tidak relevan dengan jawaban ini, tetapi relevan untuk diinformasikan kepada programmer (oleh karena itu, saya berkomentar)! Terima kasih banyak atas perpustakaan yang luar biasa ini dan atas saran Anda @ColinD!
Filipe Brito
@ColinD, ya, itu adalah kesalahan saya. Seorang kolega menambahkan google-collections yang juga memiliki namespace dan class ( List) yang sama tetapi tanpa metode sebaliknya. menghapusnya membuat jambu tersedia lagi.
AaA
Pengembang tidak selalu memiliki kendali atas perpustakaan apa yang dapat mereka gunakan, dan menambahkan perpustakaan baru untuk sesuatu yang begitu sederhana sepertinya berlebihan - terutama mengingat bahwa masalahnya dapat diselesaikan denganListIterator.previous()
Jonathan Benn
218

Gunakan metode .clone () pada Daftar Anda. Ini akan mengembalikan salinan dangkal, yang berarti akan berisi pointer ke objek yang sama, sehingga Anda tidak perlu menyalin daftar. Kemudian gunakan saja Koleksi.

Jadi,

Collections.reverse(list.clone());

Jika Anda menggunakan Listdan tidak memiliki akses, clone()Anda dapat menggunakan subList():

List<?> shallowCopy = list.subList(0, list.size());
Collections.reverse(shallowCopy);
jcalvert
sumber
21
clone()biasanya akan membuat salinan daftar. Lagi List#clone()pula , juga tidak ada.
Albert
6
Secara teknis Anda benar, antarmuka Daftar itu sendiri tidak menyediakan metode clone (). Tetapi ArrayList, LinkedList, dan Vektor semuanya berfungsi.
jcalvert
2
Saya hanya melihat implementasi dari clone(). Memang memang salinan lengkap dari daftar (itu hanya tidak mengkloning setiap objek tunggal dalam daftar tapi itu tidak pernah apa yang saya bicarakan).
Albert
21
Perhatikan bahwa Collections.reverse mengembalikan batal, sehingga Anda akan kehilangan referensi klon. Anda harus menetapkan klon ke variabel terlebih dahulu, lalu mengurutkannya.
user12722
10
subListtidak menyalin, itu hanya memberikan tampilan pada daftar yang mendasarinya, oleh karena itu membalikkan tampilan ini akan membalikkan daftar yang mendasarinya.
Roland
80

Jika saya mengerti benar maka itu adalah satu baris kode. Ini bekerja untuk saya.

 Collections.reverse(yourList);
Shakeeb Ayaz
sumber
12
Itu bukan tampilan daftar. Itu mengubah daftar.
Albert
35

Tidak terlalu elegan, tetapi jika Anda menggunakan List.listIterator (indeks int) Anda bisa mendapatkan ListIterator dua arah ke akhir daftar:

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

while (li.hasPrevious()) {
   String curr = li.previous()
}
kkress
sumber
1
Ini adalah jawaban terbaik, karena (1) tidak memerlukan perpustakaan, dan (2) tidak mengubah daftar asli, seperti yang diminta OP
Jonathan Benn
12

Collections.reverse (nums) ... Ini sebenarnya membalik urutan elemen. Kode di bawah ini harus dihargai -

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

Output: 15,94,83,42,61

Krishna Kumar Chourasiya
sumber
8
Anda hanya mengulangi jawaban yang ditulis orang lain 6 tahun lalu
Jonathan Benn
1
... dan bukan pemandangan. ini mengubah daftar.
Jason S
6

java.util.Dequememiliki descendingIterator()- jika Anda Listseorang Deque, Anda dapat menggunakannya.

Bozho
sumber
Jika Anda tidak ingin menggunakan metode descndingIterator () bawaan, sepertinya menggunakan ConcurrentLinkedDeque akan menjadi yang terbaik untuk membalik daftar yang sangat besar? Pada dasarnya cukup salin dari satu dek ke dek baru menggunakan jajak pendapat lalu menawarkan? Agak seperti hanya memiliki setumpuk kartu dan mengambil masing-masing dari atas ke tumpukan baru, secara berurutan.
djangofan
4

Saya tahu ini adalah posting lama tapi hari ini saya mencari sesuatu seperti ini. Pada akhirnya saya menulis kode sendiri:

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

Tidak disarankan untuk Daftar panjang, ini tidak dioptimalkan sama sekali. Ini semacam solusi mudah untuk skenario terkontrol (Daftar yang saya tangani tidak memiliki lebih dari 100 elemen).

Semoga ini bisa membantu seseorang.

CocheLee
sumber
2
Kode Anda memiliki satu masalah - Anda dapat memasukkan Daftar apa pun ke dalamnya, tetapi kode itu akan selalu mengembalikan Anda ArrayList (sebagai Daftar). Dan bagaimana jika saya membutuhkan LinkedList? Lebih baik memodifikasi myList, dan mengembalikan void.
Dmitry Zaytsev
2
Perhatikan bahwa ini sebenarnya bukan yang saya minta. Saya meminta semacam proxy / tampilan, bukan salinan.
Albert
4

Saya menggunakan ini:

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

}

seperti ini:

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

Anda juga dapat melakukan ini:

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;
}
jhdrosos
sumber
5
Itu bukan tampilan daftar. Tampilan adalah kebalikan dari salinan.
Albert
Daftar terbalik dari daftar kosong adalah nol ??
ShellFish
1

Anda juga dapat membalik posisi ketika Anda meminta objek:

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

Untuk daftar ukuran kecil kita dapat membuat LinkedListdan kemudian dapat menggunakan iterator descending sebagai:

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
akhil_mittal
sumber
-3

Gunakan reverse(...)metode java.util.Collectionskelas. Lulus daftar Anda sebagai parameter dan daftar Anda akan terbalik.

Collections.reverse(list);
Shubho Ghosh
sumber
1
Salinan jawaban yang ada
Karl Richter