1

I am new to using the Collections class.

I want to sort a bunch of examination marks in descending order, lets say (430,400,372,500) and then display numbers (System.out.println()) in order of merit, such that the 500 mark gets position 1, 430marks get position 2 etc.

How do I do that?

CosminO
  • 5,018
  • 6
  • 28
  • 50
Jack Wachira
  • 192
  • 4
  • 15
  • Have a look at the excellent Tutorial by Lars Vogel to [Java Collections](http://www.vogella.com/articles/JavaCollections/article.html#collectionssort). – Jost Aug 29 '13 at 07:06
  • check this link http://stackoverflow.com/questions/5894818/how-to-sort-arraylistlong-in-java-in-decreasing-order – dthien Aug 29 '13 at 07:07

3 Answers3

11

There are number of possible ways you might achieve this.

Assuming we have a List as follows...

List<Integer> marks = new ArrayList<>(5);
marks.add(430);
marks.add(400);
marks.add(372);
marks.add(500);

You could simply do...

Collections.sort(marks);
int row = 0;
for (Integer mark : marks) {
    System.out.println((++row) + ": " + mark);
}

This will output...

1: 372
2: 400
3: 430
4: 500

But wait, that's not what we want!

But with the sorted list, we can do...

Collections.reverse(marks);
row = 0;
for (Integer mark : marks) {
    System.out.println((++row) + ": " + mark);
}

Which outputs...

1: 500
2: 430
3: 400
4: 372

Much better :D

Now, if that seems like to much work, you can also use a Comparator to change the way that the items are sorted...

Collections.sort(marks, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return (o2 - o1);
    }
});

Which will produce a list in the following order...

1: 500
2: 430
3: 400
4: 372

Updated

Based on the the answer from Iterating through a list in reverse order in java, you could also do a reverse iterations of the list, if all you want to do is display the result (thanks to Boris the Spider)

Collections.sort(marks);
int row = 0;
ListIterator li = a.listIterator(a.size());
while(li.hasPrevious()) {
    System.out.println(li.previous());
}

Updated with line weights

If you're interested in knowing the "weight" on the mark, you need to modify the line marker so that it only increments when the last mark and the next mark are no longer equal...

List<Integer> marks = new ArrayList<>(Arrays.asList(new Integer[]{430, 400, 372, 400, 500}));
Collections.sort(marks, new Comparator<Integer>() {
    @Override
    public int compare(Integer o1, Integer o2) {
        return (o2 - o1);
    }
});
int row = 0;
int last = -1;
for (Integer mark : marks) {
    if (mark != last) {
        row++;
    }
    System.out.println(row + ": " + mark);
    last = mark;
}

Which outputs...

1: 500
2: 430
3: 400
3: 400
4: 372

Now, if you wanted to the output to be more like...

1: 500
2: 430
3: 400
3: 400
5: 372 // Not the skipped line...

You would need to know how many times a individual mark was matched and increment the "row" accordingly...

int row = 0;
int last = -1;
int matches = 1;
for (Integer mark : marks) {
    if (mark != last) {
        row += matches;
        matches = 1;
    } else {
        matches++;
    }
    System.out.println(row + ": " + mark);
    last = mark;
}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    You could always loop backwards rather than `reverse` the `Collection` if the only aim is to print backwards. This is trivial using a [`ListIterator`](http://stackoverflow.com/a/2102552/2071828). – Boris the Spider Aug 29 '13 at 07:16
  • thanx a lot.What if two or more students tie with the same marks...will the numbers outputted correspond? e.g (421,421,416,430)will the output be (1,2,2,4)? – Jack Wachira Aug 29 '13 at 07:19
  • The marks will be place in order, but the "row" number will still increment. They were only there for display purposes – MadProgrammer Aug 29 '13 at 07:21
  • I suppose in an ideal world the `Collection` would need to be put into a `Map` with the count of each repeated value so that the output could be `1,3,3,4`. – Boris the Spider Aug 29 '13 at 07:23
0

Try Collections.sort, Collections.reverse

Collections.sort(sampleList);
Collections.reverse(sampleList);

First Collection.sort() will arrange the assending order. And the use the Collection.reverse() it will arrage all the list values into decending order.

newuser
  • 8,338
  • 2
  • 25
  • 33
  • This answer was provided already and in more detail, what do you think your answer adds to this question? – Boris the Spider Aug 29 '13 at 07:12
  • @BoristheSpider If you think like that every question will having only one answer. I tried and post. So it takes some time – newuser Aug 29 '13 at 07:20
0

Simply you can use this

i am assuming you have array(int type) of marks

int MarksArr[] = { 421,421,416,430 }; // Array of your All Marks

        List<Integer> marks = new ArrayList<Integer>();
        for (int i = 0; i < MarksArr.length; i++)
            marks.add(MarksArr[i]);

        Collections.sort(marks);// this Will Sort in Acceding order 
        Collections.reverse(marks);// this will reverse the ArrayList (Descending order) 

  // Will Also Handle the Tie Case as per Your Comment o/p for position should be 1,2,2,4
   for (int i = 0; i < marks.size(); i++) {
        int pos = -1;
        if (i != 0)
            if (marks.get(i - 1).equals(marks.get(i)))
                pos = i;
            else
                pos = i+1;

        else {
            pos = i + 1;
        }

        System.out.println("Pos :" + pos + " Marks:" + marks.get(i));
    }

Output:

Pos :1 Marks:430
Pos :2 Marks:421
Pos :2 Marks:421
Pos :4 Marks:416
Tarsem Singh
  • 14,139
  • 7
  • 51
  • 71