Apa cara termudah untuk membalikkan ArrayList?

333

Apa cara paling sederhana untuk membalikkan ArrayList ini?

ArrayList<Integer> aList = new ArrayList<>();

//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");

while (aList.listIterator().hasPrevious())
  Log.d("reverse", "" + aList.listIterator().previous());
Ishu
sumber

Jawaban:

798
Collections.reverse(aList);

Contoh ( Referensi ):

ArrayList aList = new ArrayList();
//Add elements to ArrayList object
aList.add("1");
aList.add("2");
aList.add("3");
aList.add("4");
aList.add("5");
Collections.reverse(aList);
System.out.println("After Reverse Order, ArrayList Contains : " + aList);
Shankar Agarwal
sumber
2
@AgarwalShankar saya mendapatkan kesalahan yang diperlukan ArrayList ditemukan batal. Apakah saya melewatkan sesuatu.
Sagar Devanga
9
@SagarDevanga Daftar ini dibalik di tempat, tidak dikembalikan.
Carcigenicate
Collections.reverse (Daftar); Saya menggunakannya dalam proyek Android, berfungsi dengan baik.
Damir Varevac
22

Bukan cara paling sederhana tetapi jika Anda adalah penggemar rekursi Anda mungkin tertarik pada metode berikut untuk membalikkan ArrayList:

public ArrayList<Object> reverse(ArrayList<Object> list) {
    if(list.size() > 1) {                   
        Object value = list.remove(0);
        reverse(list);
        list.add(value);
    }
    return list;
}

Atau non-rekursif:

public ArrayList<Object> reverse(ArrayList<Object> list) {
    for(int i = 0, j = list.size() - 1; i < j; i++) {
        list.add(i, list.remove(j));
    }
    return list;
}
todd
sumber
Saya mungkin salah, tetapi dalam contoh non-rekursif Anda, tidak int jdiperbarui dengan setiap iterasi? Anda menginisialisasi j = list.size() - 1tetapi saya tidak berpikir bahwa bagian inisialisasifor loop akan diperbarui dengan setiap iterasi melakukannya?
Tony Chan
@ Turbo j tidak perlu diperbarui dengan setiap iterasi. Ini diinisialisasi ke indeks terakhir dari ArrayList dan digunakan untuk mengakses elemen terakhir. Di dalam for loop elemen terakhir dihapus dan dimasukkan ke dalam indeks i; saya bertambah hingga mencapai posisi terakhir di ArrayList.
todd
1
Ya, tetapi pada iterasi kedua, tidakkah Anda akan mendapatkan IndexOutOfBoundsExceptionkarena Anda mencoba mengakses j(indeks terakhir dari ArrayList asli) tetapi Anda sudah menghapus objek pada indeks itu?
Tony Chan
1
Maaf, jalankan saja kodenya, pasti berfungsi. Saya lupa yang add()mendorong elemen-elemen lain ke dalam array, jadi array tetap pada dasarnya ukuran konstan. Solusi menarik, terima kasih!
Tony Chan
Juga, hanya ingin tahu tetapi bagaimana Anda menemukan metode rekursif? Saya tidak berpikir itu adalah sesuatu yang biasanya saya pikirkan.
Tony Chan
13

Kuncinya di sini adalah mendefinisikan "terbalik". Orang dapat mengubah daftar di tempat, membuat salinan dalam urutan terbalik, atau membuat tampilan dalam urutan terbalik.

Cara paling sederhana, secara intuitif , adalah Collections.reverse:

Collections.reverse(myList);

Metode ini mengubah daftar di tempat . Artinya, Collections.reverseambil daftar dan timpa elemen-elemennya, tanpa meninggalkan salinan yang tidak dapat dikembalikan. Ini cocok untuk beberapa kasus penggunaan, tetapi tidak untuk yang lain; lebih jauh, ia mengasumsikan bahwa daftar dapat dimodifikasi. Jika ini dapat diterima, kami baik-baik saja.


Jika tidak, seseorang dapat membuat salinan dengan urutan terbalik :

static <T> List<T> reverse(final List<T> list) {
    final List<T> result = new ArrayList<>(list);
    Collections.reverse(result);
    return result;
}

Pendekatan ini bekerja, tetapi membutuhkan iterasi daftar dua kali. Copy constructor ( new ArrayList<>(list)) berulang di atas daftar, dan begitu juga Collections.reverse. Kami dapat menulis ulang metode ini untuk mengulangi sekali saja, jika kami cenderung:

static <T> List<T> reverse(final List<T> list) {
    final int size = list.size();
    final int last = size - 1;

    // create a new list, with exactly enough initial capacity to hold the (reversed) list
    final List<T> result = new ArrayList<>(size);

    // iterate through the list in reverse order and append to the result
    for (int i = last; i >= 0; --i) {
        final T element = list.get(i);
        result.add(element);
    }

    // result now holds a reversed copy of the original list
    return result;
}

Ini lebih efisien, tetapi juga lebih bertele-tele.

Atau, kita dapat menulis ulang di atas untuk menggunakan Java 8's streamAPI, yang beberapa orang menemukan lebih ringkas dan dapat dibaca daripada yang di atas:

static <T> List<T> reverse(final List<T> list) {
    final int last = list.size() - 1;
    return IntStream.rangeClosed(0, last) // a stream of all valid indexes into the list
        .map(i -> (last - i))             // reverse order
        .mapToObj(list::get)              // map each index to a list element
        .collect(Collectors.toList());    // wrap them up in a list
}

nb. yang Collectors.toList()membuat sangat sedikit jaminan tentang daftar hasil. Jika Anda ingin memastikan hasilnya kembali sebagai ArrayList, gunakan Collectors.toCollection(ArrayList::new)saja.


Opsi ketiga adalah membuat tampilan dalam urutan terbalik . Ini adalah solusi yang lebih rumit, dan layak dibaca lebih lanjut / pertanyaannya sendiri. Metode terbalik # Daftar Guava adalah titik awal yang layak.

Memilih implementasi yang "paling sederhana" dibiarkan sebagai latihan bagi pembaca.

naomimyselfandi
sumber
6

Solusi tanpa menggunakan ArrayList tambahan atau kombinasi metode add () dan remove (). Keduanya dapat memiliki dampak negatif jika Anda harus membalik daftar besar.

 public ArrayList<Object> reverse(ArrayList<Object> list) {

   for (int i = 0; i < list.size() / 2; i++) {
     Object temp = list.get(i);
     list.set(i, list.get(list.size() - i - 1));
     list.set(list.size() - i - 1, temp);
   }

   return list;
 }
contrapost
sumber
5
ArrayList<Integer> myArray = new ArrayList<Integer>();

myArray.add(1);
myArray.add(2);
myArray.add(3);

int reverseArrayCounter = myArray.size() - 1;

for (int i = reverseArrayCounter; i >= 0; i--) {
    System.out.println(myArray.get(i));
}
Tolunay Guney
sumber
2

Membalik ArrayList dengan cara rekursif dan tanpa membuat daftar baru untuk menambahkan elemen:

   public class ListUtil {

    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add("1");
        arrayList.add("2");
        arrayList.add("3");
        arrayList.add("4");
        arrayList.add("5");
        System.out.println("Reverse Order: " + reverse(arrayList));

    }

    public static <T> List<T> reverse(List<T> arrayList) {
        return reverse(arrayList,0,arrayList.size()-1);
    }
    public static <T> List<T> reverse(List<T> arrayList,int startIndex,int lastIndex) {

        if(startIndex<lastIndex) {
            T t=arrayList.get(lastIndex);
            arrayList.set(lastIndex,arrayList.get(startIndex));
            arrayList.set(startIndex,t);
            startIndex++;
            lastIndex--;
            reverse(arrayList,startIndex,lastIndex);
        }
        return arrayList;
    }

}
Joby Wilson Mathews
sumber
1

Kalau-kalau kita menggunakan Java 8 , maka kita bisa menggunakan Stream. ArrayList adalah daftar akses acak dan kita bisa mendapatkan aliran elemen dalam urutan terbalik dan kemudian mengumpulkannya menjadi yang baru ArrayList.

public static void main(String[] args) {
        ArrayList<String> someDummyList = getDummyList();
        System.out.println(someDummyList);
        int size = someDummyList.size() - 1;
        ArrayList<String> someDummyListRev = IntStream.rangeClosed(0,size).mapToObj(i->someDummyList.get(size-i)).collect(Collectors.toCollection(ArrayList::new));
        System.out.println(someDummyListRev);
    }

    private static ArrayList<String> getDummyList() {
        ArrayList dummyList = new ArrayList();
        //Add elements to ArrayList object
        dummyList.add("A");
        dummyList.add("B");
        dummyList.add("C");
        dummyList.add("D");
        return dummyList;
    }

Pendekatan di atas tidak cocok untuk LinkedList karena itu bukan akses acak. Kami juga dapat menggunakan instanceofuntuk memeriksa.

akhil_mittal
sumber
1

Kita juga bisa melakukan hal yang sama menggunakan java 8.

public static<T> List<T> reverseList(List<T> list) {
        List<T> reverse = new ArrayList<>(list.size());

        list.stream()
                .collect(Collectors.toCollection(LinkedList::new))
                .descendingIterator()
                .forEachRemaining(reverse::add);

        return reverse;
    }
vijayraj34
sumber
0

Sedikit lebih mudah dibaca :)

public static <T> ArrayList<T> reverse(ArrayList<T> list) {
    int length = list.size();
    ArrayList<T> result = new ArrayList<T>(length);

    for (int i = length - 1; i >= 0; i--) {
        result.add(list.get(i));
    }

    return result;
}
Yas
sumber
0

Solusi rekursif lain

 public static String reverse(ArrayList<Float> list) {
   if (list.size() == 1) {
       return " " +list.get(0);
   }
   else {
       return " "+ list.remove(list.size() - 1) + reverse(list);
   } 
 }
dt94
sumber