What is the Simplest Way to Reverse an ArrayList?
Solution 1:
Collections.reverse(aList);
Example (Reference):
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);
Solution 2:
Not the simplest way but if you're a fan of recursion you might be interested in the following method to reverse an ArrayList:
public ArrayList<Object> reverse(ArrayList<Object> list) {
if(list.size() > 1) {
Object value = list.remove(0);
reverse(list);
list.add(value);
}
return list;
}
Or non-recursively:
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;
}
Solution 3:
The trick here is defining "reverse". One can modify the list in place, create a copy in reverse order, or create a view in reversed order.
The simplest way, intuitively speaking, is Collections.reverse
:
Collections.reverse(myList);
This method modifies the list in place. That is, Collections.reverse
takes the list and overwrites its elements, leaving no unreversed copy behind. This is suitable for some use cases, but not for others; furthermore, it assumes the list is modifiable. If this is acceptable, we're good.
If not, one could create a copy in reverse order:
static <T> List<T> reverse(final List<T> list) {
final List<T> result = new ArrayList<>(list);
Collections.reverse(result);
return result;
}
This approach works, but requires iterating over the list twice. The copy constructor (new ArrayList<>(list)
) iterates over the list, and so does Collections.reverse
. We can rewrite this method to iterate only once, if we're so inclined:
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;
}
This is more efficient, but also more verbose.
Alternatively, we can rewrite the above to use Java 8's stream
API, which some people find more concise and legible than the above:
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. that Collectors.toList()
makes very few guarantees about the result list. If you want to ensure the result comes back as an ArrayList, use Collectors.toCollection(ArrayList::new)
instead.
The third option is to create a view in reversed order. This is a more complicated solution, and worthy of further reading/its own question. Guava's Lists#reverse method is a viable starting point.
Choosing a "simplest" implementation is left as an exercise for the reader.
Solution 4:
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));
}
Solution 5:
Solution without using extra ArrayList or combination of add() and remove() methods. Both can have negative impact if you have to reverse a huge list.
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;
}