reverse a list of generic typeFinding the largest mirror image of a subset/set of integers present in an array of integersContainer adaptorsEvaluate whether string is in alphabetical order or reverse alphabetical orderReverse each group of k elements in a listJava String Reverse Algorithm which is the most effcient approch?Reverse singly linked listBreaking a 32-bit value into bytes for an ArrayListGeneric Macro Generated Linked List in Ctransform list to arrayLeetCode Reverse Words in a String without using any java library
Is the worst version of the accusations against President Trump impeachable?
What pH range is suitable for cooking on teflon?
Feeling burned-out in PhD. program and thinking about dropping out
What stops one country from issuing another country's passports?
Idiom for "Ahead of its time"
How can I write characters outside a table?
In academic writing why do some recommend to avoid "announcing" the topic?
How did the USSR track Gagarin's Vostok-1 orbital flight? Was tracking capability an issue in the choice of orbit?
How many flight hours do the first retiring A380s have?
Why should interrupts be short in well configured system?
Can you combine DDR3 and DDR4?
Which quantity is mass (tensor, vector or scalar)?
What does "two ells within the selvages" mean in the Magna Carta?
is differential geometry really required to understand anything in algebraic geometry?
80s/90s sitcom with a girl who could stop time and spoke to her dad through a "gem thingy"
Why can I solve an impossible equation using linear algebra?
Pawns pushes in the center
Do any other countries aside from the US have a pledge of allegiance?
80’s or earlier short fantasy about very “sweet” neighbours
Is "to go berserk" used by native speakers or is it obsolete?
Packing disks of infinitesimal diameter on a sphere: the asymptotics of the Tammes problem
United States Towns/States Traversing by Name Puzzle
In C#, is there a way to enforce behavior coupling in interface methods or is the fact that I am trying to do that a design smell?
How to create a new file via touch if it is in a directory which doesn't exist?
reverse a list of generic type
Finding the largest mirror image of a subset/set of integers present in an array of integersContainer adaptorsEvaluate whether string is in alphabetical order or reverse alphabetical orderReverse each group of k elements in a listJava String Reverse Algorithm which is the most effcient approch?Reverse singly linked listBreaking a 32-bit value into bytes for an ArrayListGeneric Macro Generated Linked List in Ctransform list to arrayLeetCode Reverse Words in a String without using any java library
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
$begingroup$
Q: Given a list, reverse the order of its elements (don't use
collections).
Here is my solution:
public static <T> void reverse(List<T> list)
if (list.size() > 0)
T t;
t = list.get(0);
list.remove(0);
reverse(list);
list.add(t);
- I want to know if this is an efficient way of reversing a list
- Is this working for every list as input?
java reinventing-the-wheel collections
$endgroup$
|
show 4 more comments
$begingroup$
Q: Given a list, reverse the order of its elements (don't use
collections).
Here is my solution:
public static <T> void reverse(List<T> list)
if (list.size() > 0)
T t;
t = list.get(0);
list.remove(0);
reverse(list);
list.add(t);
- I want to know if this is an efficient way of reversing a list
- Is this working for every list as input?
java reinventing-the-wheel collections
$endgroup$
3
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
2
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
2
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
1
$begingroup$
It's a while since I did Java, but I'm pretty sureList<T>
is part of Collections.
$endgroup$
– Toby Speight
Sep 20 at 8:05
1
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12
|
show 4 more comments
$begingroup$
Q: Given a list, reverse the order of its elements (don't use
collections).
Here is my solution:
public static <T> void reverse(List<T> list)
if (list.size() > 0)
T t;
t = list.get(0);
list.remove(0);
reverse(list);
list.add(t);
- I want to know if this is an efficient way of reversing a list
- Is this working for every list as input?
java reinventing-the-wheel collections
$endgroup$
Q: Given a list, reverse the order of its elements (don't use
collections).
Here is my solution:
public static <T> void reverse(List<T> list)
if (list.size() > 0)
T t;
t = list.get(0);
list.remove(0);
reverse(list);
list.add(t);
- I want to know if this is an efficient way of reversing a list
- Is this working for every list as input?
java reinventing-the-wheel collections
java reinventing-the-wheel collections
edited Sep 19 at 13:29
dfhwze
13.3k3 gold badges26 silver badges95 bronze badges
13.3k3 gold badges26 silver badges95 bronze badges
asked Sep 19 at 12:21
Cristian IacobCristian Iacob
2635 bronze badges
2635 bronze badges
3
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
2
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
2
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
1
$begingroup$
It's a while since I did Java, but I'm pretty sureList<T>
is part of Collections.
$endgroup$
– Toby Speight
Sep 20 at 8:05
1
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12
|
show 4 more comments
3
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
2
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
2
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
1
$begingroup$
It's a while since I did Java, but I'm pretty sureList<T>
is part of Collections.
$endgroup$
– Toby Speight
Sep 20 at 8:05
1
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12
3
3
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
2
2
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
2
2
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
1
1
$begingroup$
It's a while since I did Java, but I'm pretty sure
List<T>
is part of Collections.$endgroup$
– Toby Speight
Sep 20 at 8:05
$begingroup$
It's a while since I did Java, but I'm pretty sure
List<T>
is part of Collections.$endgroup$
– Toby Speight
Sep 20 at 8:05
1
1
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12
|
show 4 more comments
3 Answers
3
active
oldest
votes
$begingroup$
Java doesn't handle recursion very well. And by not very well I mean it should be avoided almost every time where you cannot limit the depth to something small. To show you how bad it is let's take a look at this simple program:
public static void main(String[] args)
for(int n = 0; n < 100_000; n+=100)
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(i);
reverse(list);
System.out.println(n);
At some point in the output we can see this:
17800
17900
Exception in thread "main" java.lang.StackOverflowError
at slowness.SlowApp.reverse(SlowApp.java:24)
at slowness.SlowApp.reverse(SlowApp.java:24)
This means that on my machine with default settings I can't even handle a list of 18000 integers. Any list bigger than that just crashes the program.
Is it possible to do it without recursion then?
This has proven a little trickier than I expected when I started writing this answer.
I was thinking of 2 possible approaches.
One is to always update the list in place. Just take the last element from the list and insert it into the correct spot (insert at 0, next insert at 1, next ...). Since we don't know which kind of List we are working with this could be a really expensive operation.
The other approach is to first take a copy of all the elements. Then clear the input list. Reverse the copied elements and insert them back into the input list. The main advantage here is that we can copy them into an array which allows O(1) access to each element even for updating them.
An example implementation is then:
public static <T> void reverse2(List<T> list)
T[] array = (T[]) list.toArray();
list.clear();
for(int i = 0; i < array.length/2; i++)
T temp = array[i];
array[i] = array[array.length - i-1];
array[array.length-i-1] = temp;
for(T item : array)
list.add(item);
This implementation has no issue with a List of a million Integers.
Edit: just inserting backwards was too obvious after I tried to use list.addAll(aray) which didn't work (needs collection, not an array). I'll leave the current implementation as-is in my answer.
Note that this also isn't the most efficient way. I highly advise you to look at the implementation of the internal Collection.reverse to see a better way.
$endgroup$
$begingroup$
Argh, done it again. I keep forgettingList
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)
$endgroup$
– VisualMelon
Sep 19 at 14:15
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Isfor (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?
$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
|
show 2 more comments
$begingroup$
No and no. This is a very inefficient way to reverse, for example, a dynamic array based list (it's a different story with a linked list). With a dynamic array based (e.g. ArrayList
) The remove(0)
operation will require moving every other element in the list (linear in the length), so the whole method is quadratic in the total length of the list. It also requires a linear number of stack frames, which are actually pretty expensive and if you ask for too many the program will crash, which means this method will not work for long lists.
An efficient solution would work in linear time with a constant space requirement.
When thinking about inputs, it's important to also consider null
as a possible input. The deficient spec does not indicate what should be done with a null
input, which means you have had to make a decision, and that decision should be documented. The 'easy' (and often best) option is to explicitly test for a null
input and throw an IllegalArgumentException
exception, so that anyone using your method receives a useful error message. You could argue that your code should do nothing with a null
, but that's a bit iffy, because the spec doesn't qualify the behaviour, and that would 'silently' fail if someone passed it a null
incorrectly: throwing an exception forces any unexpected usage to be address directly, which may or may not prompt a decision change, which makes it a good 'default' choice.
There is no need here to pre-declare t
: just declare and assign it in one go:
T t = list.get(0);
This makes it easier to find out what it means. You could also make it final
in this case, so that it is entirely clear that it is only assigned once, which makes it that little bit easier to reason about the code.
When writing recursive code like this, it can pay select the 'most ideal' base case. In this instance, any list of length no more than 1 is already reversed, so you could change the if
condition to list.size() > 1
. This doesn't change the complexity, but is something of which to be aware.
$endgroup$
add a comment
|
$begingroup$
Already answered, but as task, one probably fares better with not introducing too many extra structures.
I'll immediately give an iterative version. It shows some improvements that could also be made to your recursive solution.
The recursive solution is fine, though seemingly needing a call stack the size of the list. However tail-recursion can be optimized by a good compiler (made iterative).
The iterative version needs an extra variable to hold a temporary result (the recursive call's result).
public static <T> void reverse(List<T> list)
if (list.size() > 1) // Not needed, heuristic optimisation
//List<T> reversed = new ArrayList<>(list.size());
List<T> reversed = new LinkedList<>();
while (!list.isEmpty()) // Or list.size() > 1
T t = list.remove(0);
reversed.add(t);
list.addAll(reversed);
I want to know if this is an efficient way of reversing a list
Already answered by others, but it could be astonishly good.
Nicer would be if the list
was not modified in-situ, but substituted by a new List,
as then the list.addAll(reversed)
could be exchanged for return reversed;
.
Is this working for every list as input?
Yes, though the list must not be operated upon at the same time.
There are some lists, immutable lists (that are not allowed to be changed) or lists that are backed by arrays (strudcturally immutable), that will throw an error.
$endgroup$
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229308%2freverse-a-list-of-generic-type%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Java doesn't handle recursion very well. And by not very well I mean it should be avoided almost every time where you cannot limit the depth to something small. To show you how bad it is let's take a look at this simple program:
public static void main(String[] args)
for(int n = 0; n < 100_000; n+=100)
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(i);
reverse(list);
System.out.println(n);
At some point in the output we can see this:
17800
17900
Exception in thread "main" java.lang.StackOverflowError
at slowness.SlowApp.reverse(SlowApp.java:24)
at slowness.SlowApp.reverse(SlowApp.java:24)
This means that on my machine with default settings I can't even handle a list of 18000 integers. Any list bigger than that just crashes the program.
Is it possible to do it without recursion then?
This has proven a little trickier than I expected when I started writing this answer.
I was thinking of 2 possible approaches.
One is to always update the list in place. Just take the last element from the list and insert it into the correct spot (insert at 0, next insert at 1, next ...). Since we don't know which kind of List we are working with this could be a really expensive operation.
The other approach is to first take a copy of all the elements. Then clear the input list. Reverse the copied elements and insert them back into the input list. The main advantage here is that we can copy them into an array which allows O(1) access to each element even for updating them.
An example implementation is then:
public static <T> void reverse2(List<T> list)
T[] array = (T[]) list.toArray();
list.clear();
for(int i = 0; i < array.length/2; i++)
T temp = array[i];
array[i] = array[array.length - i-1];
array[array.length-i-1] = temp;
for(T item : array)
list.add(item);
This implementation has no issue with a List of a million Integers.
Edit: just inserting backwards was too obvious after I tried to use list.addAll(aray) which didn't work (needs collection, not an array). I'll leave the current implementation as-is in my answer.
Note that this also isn't the most efficient way. I highly advise you to look at the implementation of the internal Collection.reverse to see a better way.
$endgroup$
$begingroup$
Argh, done it again. I keep forgettingList
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)
$endgroup$
– VisualMelon
Sep 19 at 14:15
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Isfor (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?
$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
|
show 2 more comments
$begingroup$
Java doesn't handle recursion very well. And by not very well I mean it should be avoided almost every time where you cannot limit the depth to something small. To show you how bad it is let's take a look at this simple program:
public static void main(String[] args)
for(int n = 0; n < 100_000; n+=100)
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(i);
reverse(list);
System.out.println(n);
At some point in the output we can see this:
17800
17900
Exception in thread "main" java.lang.StackOverflowError
at slowness.SlowApp.reverse(SlowApp.java:24)
at slowness.SlowApp.reverse(SlowApp.java:24)
This means that on my machine with default settings I can't even handle a list of 18000 integers. Any list bigger than that just crashes the program.
Is it possible to do it without recursion then?
This has proven a little trickier than I expected when I started writing this answer.
I was thinking of 2 possible approaches.
One is to always update the list in place. Just take the last element from the list and insert it into the correct spot (insert at 0, next insert at 1, next ...). Since we don't know which kind of List we are working with this could be a really expensive operation.
The other approach is to first take a copy of all the elements. Then clear the input list. Reverse the copied elements and insert them back into the input list. The main advantage here is that we can copy them into an array which allows O(1) access to each element even for updating them.
An example implementation is then:
public static <T> void reverse2(List<T> list)
T[] array = (T[]) list.toArray();
list.clear();
for(int i = 0; i < array.length/2; i++)
T temp = array[i];
array[i] = array[array.length - i-1];
array[array.length-i-1] = temp;
for(T item : array)
list.add(item);
This implementation has no issue with a List of a million Integers.
Edit: just inserting backwards was too obvious after I tried to use list.addAll(aray) which didn't work (needs collection, not an array). I'll leave the current implementation as-is in my answer.
Note that this also isn't the most efficient way. I highly advise you to look at the implementation of the internal Collection.reverse to see a better way.
$endgroup$
$begingroup$
Argh, done it again. I keep forgettingList
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)
$endgroup$
– VisualMelon
Sep 19 at 14:15
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Isfor (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?
$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
|
show 2 more comments
$begingroup$
Java doesn't handle recursion very well. And by not very well I mean it should be avoided almost every time where you cannot limit the depth to something small. To show you how bad it is let's take a look at this simple program:
public static void main(String[] args)
for(int n = 0; n < 100_000; n+=100)
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(i);
reverse(list);
System.out.println(n);
At some point in the output we can see this:
17800
17900
Exception in thread "main" java.lang.StackOverflowError
at slowness.SlowApp.reverse(SlowApp.java:24)
at slowness.SlowApp.reverse(SlowApp.java:24)
This means that on my machine with default settings I can't even handle a list of 18000 integers. Any list bigger than that just crashes the program.
Is it possible to do it without recursion then?
This has proven a little trickier than I expected when I started writing this answer.
I was thinking of 2 possible approaches.
One is to always update the list in place. Just take the last element from the list and insert it into the correct spot (insert at 0, next insert at 1, next ...). Since we don't know which kind of List we are working with this could be a really expensive operation.
The other approach is to first take a copy of all the elements. Then clear the input list. Reverse the copied elements and insert them back into the input list. The main advantage here is that we can copy them into an array which allows O(1) access to each element even for updating them.
An example implementation is then:
public static <T> void reverse2(List<T> list)
T[] array = (T[]) list.toArray();
list.clear();
for(int i = 0; i < array.length/2; i++)
T temp = array[i];
array[i] = array[array.length - i-1];
array[array.length-i-1] = temp;
for(T item : array)
list.add(item);
This implementation has no issue with a List of a million Integers.
Edit: just inserting backwards was too obvious after I tried to use list.addAll(aray) which didn't work (needs collection, not an array). I'll leave the current implementation as-is in my answer.
Note that this also isn't the most efficient way. I highly advise you to look at the implementation of the internal Collection.reverse to see a better way.
$endgroup$
Java doesn't handle recursion very well. And by not very well I mean it should be avoided almost every time where you cannot limit the depth to something small. To show you how bad it is let's take a look at this simple program:
public static void main(String[] args)
for(int n = 0; n < 100_000; n+=100)
List<Integer> list = new ArrayList<>();
for(int i = 0; i < n; i++)
list.add(i);
reverse(list);
System.out.println(n);
At some point in the output we can see this:
17800
17900
Exception in thread "main" java.lang.StackOverflowError
at slowness.SlowApp.reverse(SlowApp.java:24)
at slowness.SlowApp.reverse(SlowApp.java:24)
This means that on my machine with default settings I can't even handle a list of 18000 integers. Any list bigger than that just crashes the program.
Is it possible to do it without recursion then?
This has proven a little trickier than I expected when I started writing this answer.
I was thinking of 2 possible approaches.
One is to always update the list in place. Just take the last element from the list and insert it into the correct spot (insert at 0, next insert at 1, next ...). Since we don't know which kind of List we are working with this could be a really expensive operation.
The other approach is to first take a copy of all the elements. Then clear the input list. Reverse the copied elements and insert them back into the input list. The main advantage here is that we can copy them into an array which allows O(1) access to each element even for updating them.
An example implementation is then:
public static <T> void reverse2(List<T> list)
T[] array = (T[]) list.toArray();
list.clear();
for(int i = 0; i < array.length/2; i++)
T temp = array[i];
array[i] = array[array.length - i-1];
array[array.length-i-1] = temp;
for(T item : array)
list.add(item);
This implementation has no issue with a List of a million Integers.
Edit: just inserting backwards was too obvious after I tried to use list.addAll(aray) which didn't work (needs collection, not an array). I'll leave the current implementation as-is in my answer.
Note that this also isn't the most efficient way. I highly advise you to look at the implementation of the internal Collection.reverse to see a better way.
edited Sep 20 at 6:04
answered Sep 19 at 14:10
ImusImus
3,8933 silver badges25 bronze badges
3,8933 silver badges25 bronze badges
$begingroup$
Argh, done it again. I keep forgettingList
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)
$endgroup$
– VisualMelon
Sep 19 at 14:15
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Isfor (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?
$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
|
show 2 more comments
$begingroup$
Argh, done it again. I keep forgettingList
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)
$endgroup$
– VisualMelon
Sep 19 at 14:15
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Isfor (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?
$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
$begingroup$
Argh, done it again. I keep forgetting
List
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)$endgroup$
– VisualMelon
Sep 19 at 14:15
$begingroup$
Argh, done it again. I keep forgetting
List
is an interface in Java... @CristianIacob this should probably be the answer, because it isn't wrong and is more general (I'll address that first part in mine presently...)$endgroup$
– VisualMelon
Sep 19 at 14:15
1
1
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
$begingroup$
Note that the OP did specify that they don't want to use other collections.
$endgroup$
– VisualMelon
Sep 19 at 14:18
2
2
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
@VisualMelon I interpreted that as "don't use collections.reverse, implement it yourself". Otherwise you couldn't even use add or remove
$endgroup$
– Imus
Sep 19 at 14:23
$begingroup$
Is
for (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?$endgroup$
– Ivan García Topete
Sep 20 at 0:41
$begingroup$
Is
for (int i = array.length - 1; i >= 0; i--) list.add(array[i]);
(backwards iteration + add) different than the 1.5x iteration?$endgroup$
– Ivan García Topete
Sep 20 at 0:41
2
2
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
$begingroup$
why do you bother reversing the array, rather than just inserting in reverse order?
$endgroup$
– njzk2
Sep 20 at 5:54
|
show 2 more comments
$begingroup$
No and no. This is a very inefficient way to reverse, for example, a dynamic array based list (it's a different story with a linked list). With a dynamic array based (e.g. ArrayList
) The remove(0)
operation will require moving every other element in the list (linear in the length), so the whole method is quadratic in the total length of the list. It also requires a linear number of stack frames, which are actually pretty expensive and if you ask for too many the program will crash, which means this method will not work for long lists.
An efficient solution would work in linear time with a constant space requirement.
When thinking about inputs, it's important to also consider null
as a possible input. The deficient spec does not indicate what should be done with a null
input, which means you have had to make a decision, and that decision should be documented. The 'easy' (and often best) option is to explicitly test for a null
input and throw an IllegalArgumentException
exception, so that anyone using your method receives a useful error message. You could argue that your code should do nothing with a null
, but that's a bit iffy, because the spec doesn't qualify the behaviour, and that would 'silently' fail if someone passed it a null
incorrectly: throwing an exception forces any unexpected usage to be address directly, which may or may not prompt a decision change, which makes it a good 'default' choice.
There is no need here to pre-declare t
: just declare and assign it in one go:
T t = list.get(0);
This makes it easier to find out what it means. You could also make it final
in this case, so that it is entirely clear that it is only assigned once, which makes it that little bit easier to reason about the code.
When writing recursive code like this, it can pay select the 'most ideal' base case. In this instance, any list of length no more than 1 is already reversed, so you could change the if
condition to list.size() > 1
. This doesn't change the complexity, but is something of which to be aware.
$endgroup$
add a comment
|
$begingroup$
No and no. This is a very inefficient way to reverse, for example, a dynamic array based list (it's a different story with a linked list). With a dynamic array based (e.g. ArrayList
) The remove(0)
operation will require moving every other element in the list (linear in the length), so the whole method is quadratic in the total length of the list. It also requires a linear number of stack frames, which are actually pretty expensive and if you ask for too many the program will crash, which means this method will not work for long lists.
An efficient solution would work in linear time with a constant space requirement.
When thinking about inputs, it's important to also consider null
as a possible input. The deficient spec does not indicate what should be done with a null
input, which means you have had to make a decision, and that decision should be documented. The 'easy' (and often best) option is to explicitly test for a null
input and throw an IllegalArgumentException
exception, so that anyone using your method receives a useful error message. You could argue that your code should do nothing with a null
, but that's a bit iffy, because the spec doesn't qualify the behaviour, and that would 'silently' fail if someone passed it a null
incorrectly: throwing an exception forces any unexpected usage to be address directly, which may or may not prompt a decision change, which makes it a good 'default' choice.
There is no need here to pre-declare t
: just declare and assign it in one go:
T t = list.get(0);
This makes it easier to find out what it means. You could also make it final
in this case, so that it is entirely clear that it is only assigned once, which makes it that little bit easier to reason about the code.
When writing recursive code like this, it can pay select the 'most ideal' base case. In this instance, any list of length no more than 1 is already reversed, so you could change the if
condition to list.size() > 1
. This doesn't change the complexity, but is something of which to be aware.
$endgroup$
add a comment
|
$begingroup$
No and no. This is a very inefficient way to reverse, for example, a dynamic array based list (it's a different story with a linked list). With a dynamic array based (e.g. ArrayList
) The remove(0)
operation will require moving every other element in the list (linear in the length), so the whole method is quadratic in the total length of the list. It also requires a linear number of stack frames, which are actually pretty expensive and if you ask for too many the program will crash, which means this method will not work for long lists.
An efficient solution would work in linear time with a constant space requirement.
When thinking about inputs, it's important to also consider null
as a possible input. The deficient spec does not indicate what should be done with a null
input, which means you have had to make a decision, and that decision should be documented. The 'easy' (and often best) option is to explicitly test for a null
input and throw an IllegalArgumentException
exception, so that anyone using your method receives a useful error message. You could argue that your code should do nothing with a null
, but that's a bit iffy, because the spec doesn't qualify the behaviour, and that would 'silently' fail if someone passed it a null
incorrectly: throwing an exception forces any unexpected usage to be address directly, which may or may not prompt a decision change, which makes it a good 'default' choice.
There is no need here to pre-declare t
: just declare and assign it in one go:
T t = list.get(0);
This makes it easier to find out what it means. You could also make it final
in this case, so that it is entirely clear that it is only assigned once, which makes it that little bit easier to reason about the code.
When writing recursive code like this, it can pay select the 'most ideal' base case. In this instance, any list of length no more than 1 is already reversed, so you could change the if
condition to list.size() > 1
. This doesn't change the complexity, but is something of which to be aware.
$endgroup$
No and no. This is a very inefficient way to reverse, for example, a dynamic array based list (it's a different story with a linked list). With a dynamic array based (e.g. ArrayList
) The remove(0)
operation will require moving every other element in the list (linear in the length), so the whole method is quadratic in the total length of the list. It also requires a linear number of stack frames, which are actually pretty expensive and if you ask for too many the program will crash, which means this method will not work for long lists.
An efficient solution would work in linear time with a constant space requirement.
When thinking about inputs, it's important to also consider null
as a possible input. The deficient spec does not indicate what should be done with a null
input, which means you have had to make a decision, and that decision should be documented. The 'easy' (and often best) option is to explicitly test for a null
input and throw an IllegalArgumentException
exception, so that anyone using your method receives a useful error message. You could argue that your code should do nothing with a null
, but that's a bit iffy, because the spec doesn't qualify the behaviour, and that would 'silently' fail if someone passed it a null
incorrectly: throwing an exception forces any unexpected usage to be address directly, which may or may not prompt a decision change, which makes it a good 'default' choice.
There is no need here to pre-declare t
: just declare and assign it in one go:
T t = list.get(0);
This makes it easier to find out what it means. You could also make it final
in this case, so that it is entirely clear that it is only assigned once, which makes it that little bit easier to reason about the code.
When writing recursive code like this, it can pay select the 'most ideal' base case. In this instance, any list of length no more than 1 is already reversed, so you could change the if
condition to list.size() > 1
. This doesn't change the complexity, but is something of which to be aware.
edited Sep 19 at 14:16
answered Sep 19 at 12:44
VisualMelonVisualMelon
6,86015 silver badges44 bronze badges
6,86015 silver badges44 bronze badges
add a comment
|
add a comment
|
$begingroup$
Already answered, but as task, one probably fares better with not introducing too many extra structures.
I'll immediately give an iterative version. It shows some improvements that could also be made to your recursive solution.
The recursive solution is fine, though seemingly needing a call stack the size of the list. However tail-recursion can be optimized by a good compiler (made iterative).
The iterative version needs an extra variable to hold a temporary result (the recursive call's result).
public static <T> void reverse(List<T> list)
if (list.size() > 1) // Not needed, heuristic optimisation
//List<T> reversed = new ArrayList<>(list.size());
List<T> reversed = new LinkedList<>();
while (!list.isEmpty()) // Or list.size() > 1
T t = list.remove(0);
reversed.add(t);
list.addAll(reversed);
I want to know if this is an efficient way of reversing a list
Already answered by others, but it could be astonishly good.
Nicer would be if the list
was not modified in-situ, but substituted by a new List,
as then the list.addAll(reversed)
could be exchanged for return reversed;
.
Is this working for every list as input?
Yes, though the list must not be operated upon at the same time.
There are some lists, immutable lists (that are not allowed to be changed) or lists that are backed by arrays (strudcturally immutable), that will throw an error.
$endgroup$
add a comment
|
$begingroup$
Already answered, but as task, one probably fares better with not introducing too many extra structures.
I'll immediately give an iterative version. It shows some improvements that could also be made to your recursive solution.
The recursive solution is fine, though seemingly needing a call stack the size of the list. However tail-recursion can be optimized by a good compiler (made iterative).
The iterative version needs an extra variable to hold a temporary result (the recursive call's result).
public static <T> void reverse(List<T> list)
if (list.size() > 1) // Not needed, heuristic optimisation
//List<T> reversed = new ArrayList<>(list.size());
List<T> reversed = new LinkedList<>();
while (!list.isEmpty()) // Or list.size() > 1
T t = list.remove(0);
reversed.add(t);
list.addAll(reversed);
I want to know if this is an efficient way of reversing a list
Already answered by others, but it could be astonishly good.
Nicer would be if the list
was not modified in-situ, but substituted by a new List,
as then the list.addAll(reversed)
could be exchanged for return reversed;
.
Is this working for every list as input?
Yes, though the list must not be operated upon at the same time.
There are some lists, immutable lists (that are not allowed to be changed) or lists that are backed by arrays (strudcturally immutable), that will throw an error.
$endgroup$
add a comment
|
$begingroup$
Already answered, but as task, one probably fares better with not introducing too many extra structures.
I'll immediately give an iterative version. It shows some improvements that could also be made to your recursive solution.
The recursive solution is fine, though seemingly needing a call stack the size of the list. However tail-recursion can be optimized by a good compiler (made iterative).
The iterative version needs an extra variable to hold a temporary result (the recursive call's result).
public static <T> void reverse(List<T> list)
if (list.size() > 1) // Not needed, heuristic optimisation
//List<T> reversed = new ArrayList<>(list.size());
List<T> reversed = new LinkedList<>();
while (!list.isEmpty()) // Or list.size() > 1
T t = list.remove(0);
reversed.add(t);
list.addAll(reversed);
I want to know if this is an efficient way of reversing a list
Already answered by others, but it could be astonishly good.
Nicer would be if the list
was not modified in-situ, but substituted by a new List,
as then the list.addAll(reversed)
could be exchanged for return reversed;
.
Is this working for every list as input?
Yes, though the list must not be operated upon at the same time.
There are some lists, immutable lists (that are not allowed to be changed) or lists that are backed by arrays (strudcturally immutable), that will throw an error.
$endgroup$
Already answered, but as task, one probably fares better with not introducing too many extra structures.
I'll immediately give an iterative version. It shows some improvements that could also be made to your recursive solution.
The recursive solution is fine, though seemingly needing a call stack the size of the list. However tail-recursion can be optimized by a good compiler (made iterative).
The iterative version needs an extra variable to hold a temporary result (the recursive call's result).
public static <T> void reverse(List<T> list)
if (list.size() > 1) // Not needed, heuristic optimisation
//List<T> reversed = new ArrayList<>(list.size());
List<T> reversed = new LinkedList<>();
while (!list.isEmpty()) // Or list.size() > 1
T t = list.remove(0);
reversed.add(t);
list.addAll(reversed);
I want to know if this is an efficient way of reversing a list
Already answered by others, but it could be astonishly good.
Nicer would be if the list
was not modified in-situ, but substituted by a new List,
as then the list.addAll(reversed)
could be exchanged for return reversed;
.
Is this working for every list as input?
Yes, though the list must not be operated upon at the same time.
There are some lists, immutable lists (that are not allowed to be changed) or lists that are backed by arrays (strudcturally immutable), that will throw an error.
answered Sep 20 at 11:03
Joop EggenJoop Eggen
1,5999 silver badges14 bronze badges
1,5999 silver badges14 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f229308%2freverse-a-list-of-generic-type%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
$begingroup$
You could compare performance of this against Collection.reverse. My guess is Collection.reverse would be faster
$endgroup$
– dustytrash
Sep 19 at 12:28
2
$begingroup$
I'm voting to close this question since it's unclear what the scope of restrictions is concerning the use of collections.
$endgroup$
– dfhwze
Sep 19 at 17:19
2
$begingroup$
@Mast I'd say it's not entirely clear whether it's the Collections API, or just collections in general.
$endgroup$
– VisualMelon
Sep 19 at 21:06
1
$begingroup$
It's a while since I did Java, but I'm pretty sure
List<T>
is part of Collections.$endgroup$
– Toby Speight
Sep 20 at 8:05
1
$begingroup$
list.reversed() works just as well, but the question disallows builtin methods, and reverse slicing isn't a method. (and for pure iteration, slicing may even be faster...I'd have to check.)
$endgroup$
– Gloweye
Sep 20 at 10:12