Каков самый простой способ отменить ArrayList?

334

Какой самый простой способ отменить этот 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());
Ishu
источник

Ответы:

799
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 признан недействительным. Я что-то упускаю.
Сагар Деванга
9
@SagarDevanga Список перевернут, не возвращен.
Carcigenicate
Collections.reverse (List); Я использовал его в проекте Android, отлично работает.
Дамир Варевац
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;
}
Todd
источник
Я могу ошибаться, но в вашем нерекурсивном примере не int jобновляется с каждой итерацией? Вы инициализируете его, j = list.size() - 1но я не думаю, что раздел инициализацииfor loop обновляется с каждой итерацией, не так ли?
Тони Чан
@ Турбо j не нужно обновлять с каждой итерацией. Он инициализируется до последнего индекса ArrayList и используется для доступа к последнему элементу. Внутри цикла for последний элемент удаляется и вставляется в индекс i; я увеличивается до тех пор, пока не достигнет последней или последней позиции в ArrayList.
Todd
1
Да, но на второй итерации, вы не получите, IndexOutOfBoundsExceptionтак как пытаетесь получить доступ j(последний индекс исходного ArrayList), но вы уже удалили объект с этим индексом?
Тони Чан
1
Извините, только что запустил код, определенно работает. Я забыл, что add()толкает другие элементы вниз по массиву, поэтому массив остается практически неизменным. Интересные решения, спасибо!
Тони Чан
Кроме того, просто любопытно, но как вы пришли к рекурсивному методу? Я не думаю, что это то, о чем я обычно думаю.
Тони Чан
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;
}

Это более эффективно, но и более многословно.

В качестве альтернативы, мы можем переписать вышеупомянутое, чтобы использовать 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
}

в северном направлении это Collectors.toList()дает очень мало гарантий относительно списка результатов. Если вы хотите, чтобы результат вернулся в виде ArrayList, используйте Collectors.toCollection(ArrayList::new)вместо этого.


Третий вариант - создать представление в обратном порядке . Это более сложное решение и заслуживает дальнейшего чтения / своего вопроса. Метод обратного отображения списков в Guava - жизнеспособная отправная точка.

Выбор «простейшей» реализации оставлен читателю в качестве упражнения.

naomimyselfandi
источник
6

Решение без использования дополнительного ArrayList или комбинации методов add () и remove (). Оба могут оказать негативное влияние, если вам придется перевернуть огромный список.

 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
источник
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для проверки.

akhil_mittal
источник
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;
    }
vijayraj34
источник
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);
   } 
 }
dt94
источник