Cách đơn giản nhất để đảo ngược một ArrayList là gì?


333

Cách đơn giản nhất để đảo ngược ArrayList này là gì?

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

Câu trả lời:


796
Collections.reverse(aList);

Ví dụ ( Tham khảo ):

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

2
@AgarwalShankar tôi đang gặp lỗi yêu cầu ArrayList tìm thấy void. Tui bỏ lỡ điều gì vậy.
Sagar Devanga

9
@SagarDevanga Danh sách bị đảo ngược tại chỗ, không được trả lại.
Carcigenicate 30/05/2015

Bộ sưu tập.reverse (Danh sách); Tôi đã sử dụng nó trong một dự án Android, hoạt động tốt.
Damir Varevac

Nó không đảo ngược các yếu tố của tôi ...

22

Không phải là cách đơn giản nhất nhưng nếu bạn là người yêu thích đệ quy, bạn có thể quan tâm đến phương pháp sau để đảo ngược ArrayList:

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

Hoặc không đệ quy:

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

Tôi có thể sai, nhưng trong ví dụ không đệ quy của bạn, int jkhông được cập nhật với mỗi lần lặp? Bạn khởi tạo nó j = list.size() - 1nhưng tôi không nghĩ rằng phần khởi tạo của phần for loopđược cập nhật với mỗi lần lặp phải không?
Tony Chan

@Turbo j không cần cập nhật với mỗi lần lặp. Nó được khởi tạo đến chỉ mục cuối cùng của ArrayList và được sử dụng để truy cập phần tử cuối cùng. Trong vòng lặp for, phần tử cuối cùng được loại bỏ và chèn vào chỉ mục i; i được tăng cho đến khi nó đạt đến vị trí tiếp theo cuối cùng trong ArrayList.
chập chững

1
Có, nhưng ở lần lặp thứ hai, bạn sẽ không nhận được IndexOutOfBoundsExceptionvì bạn đang cố truy cập j(chỉ mục cuối cùng của ArrayList gốc) nhưng bạn đã xóa đối tượng tại chỉ mục đó chưa?
Tony Chan

1
Xin lỗi, chỉ cần chạy mã, chắc chắn hoạt động. Tôi quên rằng add()đẩy các phần tử khác xuống mảng, vì vậy mảng vẫn giữ nguyên kích thước không đổi. Giải pháp thú vị, cảm ơn!
Tony Chan

Ngoài ra, chỉ tò mò nhưng làm thế nào bạn đưa ra phương pháp đệ quy? Tôi không nghĩ đó là điều mà tôi thường nghĩ đến.
Tony Chan

13

Thủ thuật ở đây là định nghĩa "đảo ngược". Người ta có thể sửa đổi danh sách tại chỗ, tạo một bản sao theo thứ tự ngược lại hoặc tạo một chế độ xem theo thứ tự đảo ngược.

Cách đơn giản nhất, nói một cách trực giác , là Collections.reverse:

Collections.reverse(myList);

Phương pháp này sửa đổi danh sách tại chỗ . Đó là, Collections.reverselấy danh sách và ghi đè các yếu tố của nó, không để lại bản sao nào không bị đảo ngược. Điều này phù hợp với một số trường hợp sử dụng, nhưng không phải cho các trường hợp khác; hơn nữa, nó giả sử danh sách có thể sửa đổi. Nếu điều này được chấp nhận, chúng tôi tốt.


Nếu không, người ta có thể tạo một bản sao theo thứ tự ngược lại :

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

Cách tiếp cận này hoạt động, nhưng yêu cầu lặp lại danh sách hai lần. Trình xây dựng sao chép ( new ArrayList<>(list)) lặp qua danh sách, và cũng vậy Collections.reverse. Chúng ta có thể viết lại phương thức này để lặp lại chỉ một lần, nếu chúng ta quá nghiêng:

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

Điều này là hiệu quả hơn, nhưng cũng dài dòng hơn.

Ngoài ra, chúng tôi có thể viết lại phần trên để sử dụng streamAPI của Java 8 , một số người thấy ngắn gọn và dễ đọc hơn phần trên:

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. điều đó Collectors.toList()làm cho rất ít đảm bảo về danh sách kết quả. Nếu bạn muốn đảm bảo kết quả trở lại dưới dạng ArrayList, hãy sử dụng Collectors.toCollection(ArrayList::new)thay thế.


Tùy chọn thứ ba là tạo một khung nhìn theo thứ tự đảo ngược . Đây là một giải pháp phức tạp hơn và đáng để đọc thêm / câu hỏi của riêng nó. Danh sách # phương pháp đảo ngược của ổi là điểm khởi đầu khả thi.

Chọn một cách thực hiện "đơn giản nhất" là một bài tập cho người đọc.


6

Giải pháp mà không cần sử dụng thêm ArrayList hoặc kết hợp các phương thức add () và remove (). Cả hai có thể có tác động tiêu cực nếu bạn phải đảo ngược một danh sách lớn.

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

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

Đây là những gì tôi đã sử dụng, cảm ơn bạn!

2

Đảo ngược một ArrayList theo cách đệ quy và không tạo danh sách mới để thêm các phần tử:

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

}

1

Chỉ trong trường hợp chúng ta đang sử dụng Java 8 , thì chúng ta có thể sử dụng Stream. ArrayList là danh sách truy cập ngẫu nhiên và chúng ta có thể nhận được một luồng các phần tử theo thứ tự ngược lại và sau đó thu thập nó thành một phần mới 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;
    }

Cách tiếp cận trên không phù hợp với LinkedList vì đó không phải là truy cập ngẫu nhiên. Chúng tôi cũng có thể sử dụng instanceofđể kiểm tra là tốt.


1

Chúng tôi cũng có thể làm tương tự bằng cách sử dụng 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;
    }

0

Dễ đọc hơn một chút :)

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

0

Một giải pháp đệ quy khác

 public static String reverse(ArrayList<Float> list) {
   if (list.size() == 1) {
       return " " +list.get(0);
   }
   else {
       return " "+ list.remove(list.size() - 1) + reverse(list);
   } 
 }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.