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

Answers:


797
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,2015年

Collections.reverse(List); 我在一个Android项目中使用它,效果很好。
Damir Varevac '18

它不会扭转我的元素……

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但是我不认为每次迭代都会更新get的初始化部分for loop吗?
东尼·陈

@Turbo j不需要每次迭代都更新。它被初始化为ArrayList的最后一个索引,并用于访问最后一个元素。在for循环中,最后一个元素被删除并插入到索引i中;i递增直到到达ArrayList中的最后一个位置。
2014年

1
是的,但是在第二次迭代中,IndexOutOfBoundsException由于您正在尝试访问j(原始ArrayList的最后一个索引),但是您已经删除了该索引处的对象,因此不会得到一个?
2014年

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

这更有效,但也更冗长。

另外,我们可以重写上面的代码以使用Java 8的streamAPI,有些人发现它比上面的代码更简洁明了:

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)改用。


第三种选择是按相反的顺序创建视图。这是一个更复杂的解决方案,值得进一步阅读/提出自己的问题。番石榴的Lists#reverse方法是可行的起点。

选择“最简单”的实现留给读者练习。


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

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是随机访问列表,我们可以按相反的顺序获取元素流,然后将其收集到一个new中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);
   } 
 }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.