Reputation: 75
Edit: I should have specified that I can't use the built in sort algorithm for this.
I have an arraylist of rational numbers and I want to sort it by adding the numbers in order of highest to lowest into a new arraylist. At the moment my output is just the first rational number of the arraylist. What am I doing wrong and how can I get it to work?
public static Collection<Rational> sort(List<Rational> list){
List<Rational> sortedList = new ArrayList<Rational>();
for (Iterator<Rational> it = list.iterator(); it.hasNext(); ) {
Rational currentValue = it.next();
// Look into sortedList the position where currentValue should go into
Rational pos = null;
for (int i=0;i<sortedList.size();i++) {
// Compare currentValue with sortedList.get(i)
// to know if i is the right position for currentValue.
// If it is, assign it to pos
if(currentValue.compareTo(sortedList.get(i)) > 0){
pos = (sortedList.get(i));
}
else if((currentValue.compareTo(sortedList.get(i)) == 0)){
pos = (sortedList.get(i));
}
else if(currentValue.compareTo(sortedList.get(i)) < 0){
pos = (sortedList.get(i));
}
}
sortedList.add(pos);
}
return sortedList;
}
Upvotes: 2
Views: 498
Reputation: 649
Create your own Comparator implementation. In this manner, you can define any number of comparators if your sorting needs change depending on context.
public static Comparator<Rational> comparator = new Comparator<Rational>() {
@Override
public int compare ( Rational o1, Rational o2 ) {
// Sort logic here
}
};
public static Collection<Rational> sort( List<Rational> list ) {
List<Rational> sortedList = new ArrayList<Rational>(list);
Collections.sort( sortedList, comparator );
return sortedList;
}
Upvotes: 0
Reputation: 123
Edit: corrected i to j in inner loop
The previous answers provide "the best" way to go about this. However, if you'd like to know how to fix your original take on the problem, here's a way to make your original code work like you wanted it to work. I also changed the iterator to index syntax so that both lists are handled the same way for more readable code. Other way to go about this would have been to make also sortedList use iterator. If you'd change the comparison > 0 to comparison < 0, you'd get reverse order.
public static Collection<Rational> sort(List<Rational> list){
List<Rational> sortedList = new ArrayList<Rational>();
for (int i=0;i < rationalList.size();i++) {
Rational currentValue = rationalList.get(i);
int pos = sortedList.size(); // default is to the end of the list
for (int j=0;j<sortedList.size();j++) {
int comparison = currentValue.compareTo(sortedList.get(j))
//this is the right position if the currentValue is greater or equal
//to the sorted value at this position
if(comparison > 0 || comparison == 0){
pos = j;
break;
}
}
sortedList.add(pos, currentValue);
}
return sortedList;
}
The problems with your original code were:
1) You weren't looking for the int index value of the right position, you had Rational position, which feels a bit weird 2) In your sortedList check phase, you called pos = (sortedList.get(i)); no matter what the comparison was 3) You added the value of pos itself to the sortedList: sortedList.add(pos);
So the corrections were:
1) We are looking for the int index value of the right position in the current sortedList 2) We are only interested in the position, where the new value is either greater or equal to the current sorted value at that position 3) We put the currentValue into the sortedList only to the specific index that we found by comparison. Default position is at the end.
Upvotes: 0
Reputation: 121712
Using tools available in the JDK, this is what you can do:
private static final Comparator<Rational> INVERSE_RATIONAL
= new Comparator<Rational>()
{
@Override
public int compare(final Rational a, final Rational b)
{
return b.compareTo(a);
}
}
// ...
public static Collection<Rational> sort(final List<Rational> list)
{
// Note: supposes Java 7
final List<Rational> ret = new ArrayList<>(ret);
Collections.sort(ret, INVERSE_RATIONAL);
return ret;
}
EDIT @Makoto rightly points to Collections.reverse()
, which makes the above code even more simple:
// No need for a custom Comparator...
public static Collection<Rational> sort(final List<Rational> list)
{
// Note: supposes Java 7
final List<Rational> ret = new ArrayList<>(ret);
Collections.sort(ret);
Collections.reverse(ret);
return ret;
}
Upvotes: 1
Reputation: 11440
You should use Collections.sort
as its fast, efficient and you can count on it not having bugs. Your code has some bugs, take this line for instance:
// Look into sortedList the position where currentValue should go into
Rational pos = null;
Here you say its the position which is correct but you have a Rational
Object where you should have an int
value. For an insertion sort you need to go through the list until you find the correct spot to place the object. So here we go through the list until we find a good position for the object, then we add that object at the position.
Your inner loop should look like this:
// Look into sortedList the position where currentValue should go into
int pos = 0;
for (int i=0;i<sortedList.size();i++) {
// Compare currentValue with sortedList.get(i)
// to know if i is the right position for currentValue.
// If it is, assign it to pos
if(currentValue.compareTo(sortedList.get(i)) > 0) {
// For lowest to highest sort, uncomment this
//pos = i+1;
}
else if((currentValue.compareTo(sortedList.get(i)) == 0)){
pos = i;
}
else if(currentValue.compareTo(sortedList.get(i)) < 0){
// For highest to lowest.
pos = i+1;
}
}
sortedList.add(pos, currentValue);
There are better ways to write this code but I left it as close to what you had as possible.
Upvotes: 0
Reputation: 106390
Since your elements appear to be Comparable
, you can do two things:
Collections.sort
to sort them in ascending order (lowest to highest),Collections.reverse
to reverse the order.Both of these operations modify the list in place. If this is undesirable, copy the contents of the list to an intermediate list and modify that.
Collections.sort(sortedList);
Collections.reverse(sortedList);
You could copy the contents to an intermediate list, and mutate that as well:
List<Rational> sortedList = new ArrayList<Rational>();
for(Rational rational : list) {
sortedList.add(rational);
}
Collections.sort(sortedList);
Collections.reverse(sortedList);
Upvotes: 1