1

Collections.sort() is not working as expected. When I put Collections.reverse() just before Collections.sort(), the order of the ArrayList is different. How can that be? It's the same data, just reverted.

    messages = new ArrayList<Message>();
    messageDatabase.getConditionBuilder().setSortOrder(DatabaseHelper.KEY_MESSAGE_TIME + " DESC");
    messageDatabase.getConditionBuilder().setSqlLimit(100);
    messages.addAll(messageDatabase.getList());

    // different results if I remove the reverse line
    Collections.reverse(messages);
    Collections.sort(messages);

    messageAdapter = new MessageAdapter(this, R.layout.list_message_item, messages);
    messageAdapter.setIsPrivateChat(true);
    listView.setAdapter(messageAdapter);

My Message model implements comparable

@Override
public int compareTo(Message another) {
    return Float.compare(time, another.getTime());
}

Update: I've updated my code a little bit and added debugging. Ordering now by localTime, which is the unix timestamp in microseconds. There are no equal timestamps.

@Override
public int compareTo(Message another) {
    return Float.compare(localTime, another.getLocalTime());
}

Reading from database:

    messages = new ArrayList<Message>();
    messageDatabase.getConditionBuilder().setSortOrder(DatabaseHelper.KEY_MESSAGE_LOCAL_TIME + " DESC");
    messageDatabase.getConditionBuilder().setSqlLimit(100);

    messages.addAll(messageDatabase.getList());
    for (Message m : messages) {
        Log.i("debug", "time unsorted: " + m.getLocalTime());
    }
    Collections.sort(messages);
    for (Message m : messages) {
        Log.i("debug", "time: " + m.getLocalTime());
    }

Result (shortened and cut the first 6 equal numbers):

06-21 15:56:14.734: I/debug(13886): time unsorted: 4607969
06-21 15:56:14.734: I/debug(13886): time unsorted: 4607303
06-21 15:56:14.734: I/debug(13886): time unsorted: 4591162
06-21 15:56:14.734: I/debug(13886): time unsorted: 3372601
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338542
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338514
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338481
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338455
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338415
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338375
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338339
06-21 15:56:14.734: I/debug(13886): time unsorted: 3338244
06-21 15:56:14.734: I/debug(13886): time: 3338542
06-21 15:56:14.734: I/debug(13886): time: 3338514
06-21 15:56:14.734: I/debug(13886): time: 3338481
06-21 15:56:14.734: I/debug(13886): time: 3338455
06-21 15:56:14.734: I/debug(13886): time: 3338415
06-21 15:56:14.734: I/debug(13886): time: 3338375
06-21 15:56:14.734: I/debug(13886): time: 3338339
06-21 15:56:14.734: I/debug(13886): time: 3338244
06-21 15:56:14.734: I/debug(13886): time: 3372601
06-21 15:56:14.734: I/debug(13886): time: 4607969
06-21 15:56:14.734: I/debug(13886): time: 4607303
06-21 15:56:14.734: I/debug(13886): time: 4591162

But actually I expect the sorted array to look like this:

06-21 15:56:14.734: I/debug(13886): time: 3338244
06-21 15:56:14.734: I/debug(13886): time: 3338339
06-21 15:56:14.734: I/debug(13886): time: 3338375
06-21 15:56:14.734: I/debug(13886): time: 3338415
06-21 15:56:14.734: I/debug(13886): time: 3338455
06-21 15:56:14.734: I/debug(13886): time: 3338481
06-21 15:56:14.734: I/debug(13886): time: 3338514
06-21 15:56:14.734: I/debug(13886): time: 3338542
06-21 15:56:14.734: I/debug(13886): time: 3372601
06-21 15:56:14.734: I/debug(13886): time: 4591162
06-21 15:56:14.734: I/debug(13886): time: 4607303
06-21 15:56:14.734: I/debug(13886): time: 4607969

Did I missunderstood Collections.sort()?

Chris
  • 4,255
  • 7
  • 42
  • 83

2 Answers2

4

Collections.sort uses stable sorting algorithm (modified merge sort), that is, if some items have equal keys on which the collection is being sorted, their mutual order will be intact after sorting.

That's why reversing your collection changes ordering after sort. Of course, only items with equal sorting keys will have different order.

hotkey
  • 140,743
  • 39
  • 371
  • 326
2

Long.compare(long, long) should be used to compare long values.

What's wrong with using == to compare floats in Java?


Consider the following collection of items, A-F, each with an integer property, size.

A(1)
B(1)
C(2)
D(4)
E(5)
F(2)

Collections.reverse() would do:

F(2)
E(5)
D(4)
C(2)
B(1)
A(1)

then Collections.sort() would reorder items based on the size, but otherwise leave the ordering intact:

E(5)
D(4)
F(2)
C(2)
B(1)
A(1)

such that if you just did Collections.sort() without reversing the collection first, A&B and C&F would stay in the same order:

E(5)
D(4)
C(2)
F(2)
A(1)
B(1)
Community
  • 1
  • 1
ataulm
  • 15,195
  • 7
  • 50
  • 92
  • `Long.compare()` requires API 19. So I'm fine checking if a > b and return 1 or -1? – Chris Jun 21 '15 at 14:37
  • 1
    if you click through, you'll see it's a one-liner static function: `return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);` – ataulm Jun 21 '15 at 14:45