eddiewastaken
eddiewastaken

Reputation: 832

Collections.sort() not sorting with compareTo Override

As the title states - here's my Packet class - I'm trying to sort into ascending order of packetNum:

public class Packet implements Comparable<Packet>{
    private short packetNum;
    private short authKey;
    private byte[] audio;

    public Packet()
    {
        packetNum = 0;
        authKey = 0;
        audio = null;
    }

    public Packet(short packetNum, short authKey, byte[] audio)
    {
        this.packetNum = packetNum;
        this.authKey = authKey;
        this.audio = audio;
    }

    @Override
    public int compareTo(Packet other) {
        int cmp = 0;
        if (this.packetNum < other.packetNum) {
            cmp = -1;
        }
        if (this.packetNum == other.packetNum) {
            cmp = 0;
        }
        else {
            cmp = 1;
        }
        return cmp;
    }
}

And here's my sorting code in another class' main (inside a while loop):

//Packet constructed
Packet received = new Packet(packetNumReceived, authKeyReceived, encryptedAudio);

//Get packet num
short packetNum = received.getPacketNum();

//Hold block for reordering (16 packets)
ArrayList<Packet> block = new ArrayList<Packet>();

while (running) {
    //Add packet to ArrayList
    block.add(received);
    System.out.println(packetNum);
    //Re-order packets
    if (block.size() == 16) {
        Collections.sort(block);
        for (int i = 0; i < block.size(); i++) {
            //print out the sorted packet numbers
            System.out.println(block.get(i).getPacketNum());
            player.playBlock(block.get(i).getAudio());
        }
        block.clear();
    }
}

The packet numbers printed are in the same (incorrect) order, before and after the sort. I've also check the array elements directly, and the order is not changed at all. These sections of code are the only time the Packet class is touched/referenced at all, not sure what I'm doing wrong. These are my only 2 classes, and there are no reused variable names across them.

Upvotes: 1

Views: 124

Answers (3)

aran
aran

Reputation: 11880

@Override
public int compareTo(Packet other) {
    int cmp = 0;
    if (this.packetNum < other.packetNum) {
        cmp = -1;
    }
    if (this.packetNum == other.packetNum) {
        cmp = 0;
    }
    else {
        cmp = 1;
    }
    return cmp;
}

In this code, you are returning 1 if the comparison this.packetNum == other.packetNum evaluates to false even if you wanted to return -1.

You forgot an else:

    (...) 
    else if (this.packetNum == other.packetNum) {
        cmp = 0;
    }
    (...)

Upvotes: 5

David Conrad
David Conrad

Reputation: 16379

You're always returning 1 when the packetNum doesn't match because you're missing an else if.

@Override
public int compareTo(Packet other) {
    int cmp = 0; // default to zero
    if (this.packetNum < other.packetNum) {
        cmp = -1;  // set to -1 in one case
    } // MISSING ELSE!
    if (this.packetNum == other.packetNum) {
        cmp = 0;  // set to zero if equal
    }
    else {
        cmp = 1;  // set to 1 if NOT EQUAL!
    }
    return cmp;
}

It's also true, as other have pointed out, that subtracting them or using Short.compare would make this code more terse and readable.

Upvotes: 3

LppEdd
LppEdd

Reputation: 21144

Don't code what's already coded for you, use

Short.compare(this.packetNum, other.packetNum);

Javadoc

Upvotes: 1

Related Questions