Reputation: 1065
I'm doing some exercises on generic programming; is there a way to take a class that implements List and return a reversed version of that same class? It seems this should be feasible as this, at least taking the term at face value, is "generic programming" writ large.
Maybe by performing an in-place reversal? I also considered Collections.reverse(), but it's a void method.
Here is my attempt and demo:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Arrays;
public class ReverseDemo {
public static <T> List<T> reverse(List<T> list) {
List<T> reversed = new ArrayList<T>();
for (int i = list.size() - 1; i >= 0; i--) {
reversed.add(list.get(i));
}
return reversed;
}
public static void main(String[] args) {
LinkedList<Integer> linkedInt = new LinkedList<Integer>();
ArrayList<Double> arrayDouble = new ArrayList<Double>();
for (int k = 0; k < 10; k++) {
double doubleNum = 10*Math.random();
int intNum = (int) (10*Math.random());
linkedInt.add(intNum);
arrayDouble.add(doubleNum);
}
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse(linkedInt).toArray()));
System.out.println(reverse(linkedInt) instanceof LinkedList<?>); // false
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse(arrayDouble).toArray()));
System.out.println(reverse(arrayDouble) instanceof ArrayList<?>); // true
}
}
Incidentally this is my first post here, does anyone know the best way to post code directly from Eclipse while preserving the spacing and indentation therefrom? I've used the four-spaces method specified here, but it's a bit inconsistent.
Upvotes: 5
Views: 3657
Reputation: 1065
Thanks for the replies everyone. I wrote a method reverse2 which works at least for implementing classes ArrayList and LinkedList. Not sure how efficient it is.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Arrays;
// See http://stackoverflow.com/questions/16799066/return-reversed-generic-list-type-in-java.
public class ReverseDemo {
public static <T> List<T> reverse1(List<T> list) {
List<T> reversed = new ArrayList<T>();
for (int i = list.size() - 1; i > -1; i--) {
reversed.add(list.get(i));
}
return reversed;
}
public static <T> List<T> reverse2(List<T> list) {
int size = list.size();
ArrayList<T> obArray = new ArrayList<T>();
obArray.addAll(list);
ListIterator<T> iter = list.listIterator();
for (int i = 0; i < size; i++) {
iter.next();
iter.set(obArray.get(size - 1 - i));
}
return list;
}
public static void main(String[] args) {
LinkedList<Integer> linkedInt = new LinkedList<Integer>();
ArrayList<Double> arrayDouble = new ArrayList<Double>();
for (int k = 0; k < 10; k++) {
double doubleNum = 10*Math.random();
int intNum = (int) (10*Math.random());
linkedInt.add(intNum);
arrayDouble.add(doubleNum);
}
TextIO.putln("Testing reverse1.");
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse1(linkedInt).toArray()));
TextIO.putln("LinkedList structure preserved?");
System.out.println(reverse1(linkedInt) instanceof LinkedList<?>);
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse1(arrayDouble).toArray()));
TextIO.putln("ArrayList structure preserved?");
System.out.println(reverse1(arrayDouble) instanceof ArrayList<?>);
TextIO.putln("\nTesting reverse2.");
// LinkedList<Integer> demo
System.out.println(Arrays.toString(linkedInt.toArray()));
System.out.println(Arrays.toString(reverse2(linkedInt).toArray()));
TextIO.putln("LinkedList structure preserved?");
System.out.println(reverse2(linkedInt) instanceof LinkedList<?>);
// ArrayList<Double> demo
System.out.println(Arrays.toString(arrayDouble.toArray()));
System.out.println(Arrays.toString(reverse2(arrayDouble).toArray()));
TextIO.putln("ArrayList structure preserved?");
System.out.println(reverse2(arrayDouble) instanceof ArrayList<?>);
}
}
console output:
Testing reverse1. [8, 0, 1, 9, 3, 4, 3, 7, 6, 3] [3, 6, 7, 3, 4, 3, 9, 1, 0, 8] LinkedList structure preserved? false [8.301783107294664, 5.434068303620735, 9.095396759542615, 0.41823972682620836, 9.56659902304762, 3.2560723280079085, 4.037362000077436, 9.731919590391389, 0.5243645318825874, 5.9432185528462975] [5.9432185528462975, 0.5243645318825874, 9.731919590391389, 4.037362000077436, 3.2560723280079085, 9.56659902304762, 0.41823972682620836, 9.095396759542615, 5.434068303620735, 8.301783107294664] ArrayList structure preserved? true
Testing reverse2. [8, 0, 1, 9, 3, 4, 3, 7, 6, 3] [3, 6, 7, 3, 4, 3, 9, 1, 0, 8] LinkedList structure preserved? true [8.301783107294664, 5.434068303620735, 9.095396759542615, 0.41823972682620836, 9.56659902304762, 3.2560723280079085, 4.037362000077436, 9.731919590391389, 0.5243645318825874, 5.9432185528462975] [5.9432185528462975, 0.5243645318825874, 9.731919590391389, 4.037362000077436, 3.2560723280079085, 9.56659902304762, 0.41823972682620836, 9.095396759542615, 5.434068303620735, 8.301783107294664] ArrayList structure preserved? true
Upvotes: 0
Reputation: 5415
This seems to work:
import java.util.*;
public class ReverseListDemo
{
public static void main(String[] args)
{
List<String> original = Arrays.asList("A", "B", "C");
List<String> reversal = reverse(original);
System.out.println("Original: " + original);
System.out.println("Reversal: " + reversal);
}
public static <T> List<T> reverse(List<T> list)
{
T[] objects = (T[]) list.toArray();
List<T> copy = Arrays.asList(objects);
Collections.reverse(copy);
return copy;
}
}
Upvotes: 0
Reputation: 4262
try following
public static <T> List<T> reverse(List<T> list) {
List<T> reversed=null;
try {
reversed = list.getClass().newInstance();
Collections.reverse(list);
reversed.addAll(list);
} catch (InstantiationException | IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
return reversed;
}
Upvotes: 2
Reputation: 109
The Guava library has a nice, non-destructive solution to the problem. See Lists.reverse(List).
They define a suite of ReverseList
classes that wrap the input List
. From there, it's just a matter of translating all of calls (although "just" might be understating things a bit).
Upvotes: 3
Reputation: 22504
If you want to preserve the original list, you can try using:
originalList.getClass().newInstance()
That is not a 100% correct solution as it may throw if the original class does not have a default constructor. However, most collections have default constructors that create empty instances.
Upvotes: 2
Reputation: 200148
All java.util
implementations of List
are cloneable, so you could use that, but sadly not without resorting to reflection. While on the reflection chapter, you may also use the copy-constructor, which is also sported by all Java's collections.
There is no fully general approach to non-destructive reversing, unfortunately.
Destructive reversing, on the other hand, is too trivial to be interesting.
Upvotes: 1
Reputation: 7507
The Collections.reverse()
might be void, but that's only because you should be passing in the List to be reversed.
List<T> myList = ...;
Collections.reverse(myList);
You now have a reversed list.
Upvotes: 1