I have an ordered ArrayList of strings: I wrote this static method to keep it sorted, i use it every time an element is is added to the ArrayList.
Using listIterator, I start from the last value of ArrayList N: if N-1 comes after N I invert the two values. Then I go to cell n-1, and repeat the same procedure, until i reach the end of ArrayList.
In this code I am unable to invert current with prev: what am I doing wrong?
public static void sort(ArrayList arr, String s){
if(arr.size()>1){
ListIterator<String> iterator = arr.listIterator(arr.size());
while(iterator.hasPrevious()){
String current = iterator.previous();
String prev = iterator.previous();
if(compare(current,prev) < 0){
iterator.set(current);
iterator.next();
iterator.set(prev);
iterator.previous();
} else {
break;
}
}
}
}
From documentation of ListIterator#set(E e)
we can read
Replaces the last element returned by
next()
orprevious()
with the specified element
So lets see what happens in your swapping code for data like arr=["b", "c", "a"]
.
I will mark position of iterator with <
or >
to point out direction of potential set
method.
So it will be
[elementE] < elementF
if it was called after next()
which returned elementE
elementD > [elementE]
if it was called after previous()
which returned elementE
iterator.set(current); //1
iterator.next(); //2
iterator.set(prev); //3
iterator.previous(); //4
Before its execution, state of your application (iterator and variables) is
//current = "a"; prev="c", arr=["b", "c", "a"]
"b" > "c" "a"
|
position of iterator
So since iterator points to element "c"
it would be replaced if we call set
now.
After calling iterator.set(current);
where current="a"
state of application will change to
//current = "a"; prev="c", arr=["b", "a", "a"]
"b" > "a" "a" //`iterator.set` doesn't affect "position" of iterator
Now after iterator.next();
it will become
//current = "a"; prev="c", arr=["b", "a", "a"]
"b" "a" < "a" //notce iterator was moved between "a" and "a"
//but points at *left* "a"
Take a look at direction of iterator (which is <
) and again read documentation quoted at start of this answer. Currently iterator.set(prev);
will replace "a"
in the middle, not at the end because it was middle element which was returned by either next()
or previous()
as last element.
If you want to replace last "a"
you need iterator to "point at" that element. So you want to create situation like
"b" "a" > "a"
- points from left"b" "a" "a" <
- points from right(also remember to set iterator after swapping in position like "b" "a" < "a"
or "b" "a" > "a"
so it would be "before" two next elements which we want to compare).
In case 1 your swapping code can look like
//"b" > "c" "a"
iterator.set(current); //"b" > current "a"
iterator.next(); //"b" current < "a"
iterator.next(); //"b" current "a" <
iterator.previous(); //"b" current > "a"
iterator.set(prev); //"b" current > prev
(I will leave code for case 2 as your homework)
BTW you need to handle case where new element is smallest in entire list (like in scenario in current answer with ["b", "c", "a"]
(you will need nested iterator.hasPrevious()
)