วิธีที่ง่ายที่สุดในการกลับรายการ ArrayList คืออะไร


333

วิธีที่ง่ายที่สุดในการกลับรายการ ArrayList นี้คืออะไร

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

คำตอบ:


798
Collections.reverse(aList);

ตัวอย่าง ( การอ้างอิง ):

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 ฉันได้รับข้อผิดพลาดที่จำเป็นต้องพบ ArrayList เป็นโมฆะ ฉันพลาดอะไรไปรึเปล่า.
Sagar Devanga

9
@SagarDevanga รายการถูกกลับรายการในสถานที่ไม่ส่งคืน
Carcigenicate

Collections.reverse (รายชื่อ); ฉันใช้มันในโครงการ Android ทำงานได้ดี
Damir Varevac

22

ไม่ใช่วิธีที่ง่ายที่สุด แต่ถ้าคุณเป็นแฟนของการสอบถามซ้ำคุณอาจสนใจวิธีต่อไปนี้เพื่อย้อนกลับ ArrayList:

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

หรือไม่ใช่แบบเรียกซ้ำ:

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

ฉันอาจจะผิด แต่ในตัวอย่างที่ไม่ใช่แบบเรียกซ้ำของคุณจะไม่int jได้รับการอัปเดตทุกครั้งหรือไม่ คุณเริ่มต้นมันj = list.size() - 1แต่ฉันไม่คิดว่าส่วนการเริ่มต้นของการfor loopได้รับการปรับปรุงด้วยการทำซ้ำแต่ละครั้งหรือไม่
Tony Chan

@ Turbo j ไม่จำเป็นต้องได้รับการอัพเดทซ้ำทุกครั้ง มันจะเริ่มต้นไปที่ดัชนีสุดท้ายของ ArrayList และใช้ในการเข้าถึงองค์ประกอบสุดท้าย ในห่วงสำหรับองค์ประกอบสุดท้ายจะถูกลบและแทรกลงในดัชนีฉัน; i ถูกเพิ่มค่าจนกว่าจะถึงตำแหน่งถัดจากตำแหน่งสุดท้ายใน ArrayList
todd

1
ใช่ แต่ในการวนซ้ำครั้งที่สองคุณจะไม่ได้รับIndexOutOfBoundsExceptionเนื่องจากคุณพยายามเข้าถึงj(ดัชนีสุดท้ายของ ArrayList ดั้งเดิม) แต่คุณได้ลบวัตถุที่ดัชนีนั้นหรือไม่
Tony Chan

1
ขออภัยเพิ่งรันโค้ดทำงานได้อย่างแน่นอน ฉันลืมที่add()ผลักองค์ประกอบอื่น ๆ ลงอาร์เรย์ดังนั้นอาร์เรย์จึงมีขนาดคงที่ โซลูชั่นที่น่าสนใจขอบคุณ!
Tony Chan

นอกจากนี้แค่อยากรู้อยากเห็น แต่คุณคิดวิธีการแบบวนซ้ำได้อย่างไร? ฉันไม่คิดว่าเป็นสิ่งที่ปกติฉันจะคิดถึง
Tony Chan

13

เคล็ดลับที่นี่กำหนด "ย้อนกลับ" หนึ่งสามารถแก้ไขรายการในสถานที่สร้างสำเนาในลำดับย้อนกลับหรือสร้างมุมมองในลำดับที่กลับรายการ

วิธีที่ง่ายที่สุดคือพูดโดยสังหรณ์ใจคือCollections.reverse:

Collections.reverse(myList);

วิธีการนี้จะปรับเปลี่ยนรายการในสถานที่ นั่นคือCollections.reverseใช้รายการและเขียนทับองค์ประกอบของมันโดยไม่มีการคัดลอกที่ไม่มีการย้อนกลับ เหมาะสำหรับกรณีการใช้งานบางกรณี แต่ไม่เหมาะสำหรับผู้อื่น นอกจากนี้จะถือว่ารายการสามารถแก้ไขได้ หากเป็นที่ยอมรับเราก็ดี


หากไม่สามารถสร้างสำเนาในลำดับที่กลับกันได้:

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

วิธีการนี้ใช้งานได้ แต่ต้องวนซ้ำในรายการสองครั้ง ตัวสร้างการคัดลอก ( new ArrayList<>(list)) วนซ้ำตามรายการและทำCollections.reverseเช่นนั้น เราสามารถเขียนวิธีนี้ซ้ำอีกครั้งเพียงครั้งเดียวหากเราเอียงมาก:

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

นี้มีประสิทธิภาพมากขึ้น แต่ยัง verbose มากขึ้น

นอกจากนี้เราสามารถเขียนข้างต้นใหม่เพื่อใช้streamAPI ของ Java 8 ซึ่งบางคนพบว่ากระชับและอ่านง่ายกว่าข้างต้น:

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 ที่Collectors.toList()ทำให้มีการรับประกันน้อยมากเกี่ยวกับรายการผลลัพธ์ หากคุณต้องการมั่นใจว่าผลลัพธ์จะกลับมาเป็น ArrayList ให้ใช้Collectors.toCollection(ArrayList::new)แทน


ตัวเลือกที่สามคือการสร้างมุมมองในการสั่งซื้อกลับรายการ นี่เป็นวิธีที่ซับซ้อนกว่าและคุ้มค่าที่จะอ่านเพิ่มเติม / คำถามของมันเอง รายการ # ย้อนกลับของ Guava เป็นจุดเริ่มต้นที่ทำงานได้

การเลือกการใช้งาน "ที่ง่ายที่สุด" จะถูกนำไปใช้เป็นแบบฝึกหัดสำหรับผู้อ่าน


6

วิธีการแก้ปัญหาโดยไม่ต้องใช้ ArrayList พิเศษหรือการรวมกันของวิธีการเพิ่ม () และลบ () ทั้งคู่มีผลกระทบด้านลบหากคุณต้องย้อนกลับรายการใหญ่

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

2

การกลับรายการ ArrayList ด้วยวิธีแบบเรียกซ้ำและไม่สร้างรายการใหม่สำหรับการเพิ่มองค์ประกอบ:

   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

ในกรณีที่เราใช้Java 8เราจะสามารถใช้งาน Stream ได้ ArrayList 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;
    }

วิธีการข้างต้นไม่เหมาะสำหรับ LinkedList เนื่องจากไม่ใช่การเข้าถึงแบบสุ่ม เรายังสามารถใช้ประโยชน์จากinstanceofการตรวจสอบเช่นกัน


1

เราสามารถทำได้เช่นเดียวกันโดยใช้ 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

สามารถอ่านได้มากขึ้น :)

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

อีกวิธีแก้ปัญหาซ้ำ

 public static String reverse(ArrayList<Float> list) {
   if (list.size() == 1) {
       return " " +list.get(0);
   }
   else {
       return " "+ list.remove(list.size() - 1) + reverse(list);
   } 
 }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.