Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TreeMap not sorting properly

I am trying to sort a TreeMap according to "weight". But for some reason it is deleting entries with the same weight value even though the keys are different.

Below is the code:

class Edge  {
    int source;
    int destination;
    int weight;

    public Edge(int source, int destination, int weight) {
        this.source = source;
        this.destination = destination;
        this.weight = weight;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + destination;
        result = prime * result + source;
        result = prime * result + weight;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Edge other = (Edge) obj;
        if (destination != other.destination)
            return false;
        if (source != other.source)
            return false;
        if (weight != other.weight)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Edge [source=" + source + ", destination=" + destination + ", weight=" + weight + "]";
    }
}

Data of HashMap:

{Edge [source=0, destination=1, weight=5]=5, Edge [source=1, destination=2, weight=4]=4, Edge [source=2, destination=3, weight=5]=5, Edge [source=0, destination=3, weight=6]=6, Edge [source=0, destination=2, weight=3]=3, Edge [source=1, destination=3, weight=7]=7}

Map<Edge, Integer> treemap = new TreeMap<>(new MyWeightComp());
    treemap.putAll(map);

Comparator of the Treemap:

 class MyWeightComp implements Comparator<Edge>{

    @Override
    public int compare(Edge e1, Edge e2) {
        return e1.weight-e2.weight;
    }
}

Data after sorting:

{Edge [source=0, destination=2, weight=3]=3, Edge [source=1, destination=2, weight=4]=4, Edge [source=0, destination=1, weight=5]=5, Edge [source=0, destination=3, weight=6]=6, Edge [source=1, destination=3, weight=7]=7}

So you can see that, for some reason the data with the same weight is getting deleted even though the key is a combination of source and destination.

like image 283
user1986787 Avatar asked Jan 28 '23 04:01

user1986787


2 Answers

All the Maps delete duplicates and if compareTo returns 0, it is assumed to be the same key.

class MyWeightComp implements Comparator<Edge> {

    @Override
    public int compare(Edge e1, Edge e2) {
        int cmp = Integer.compare(e1.weight, e2.weight); // handle overflows.
        if (cmp == 0)
            cmp = Integer.compare(e1.source, e2.source);
        if (cmp == 0)
            cmp = Integer.compare(e1.destination, e2.destination);
        return cmp;
    }
}

If you have fields which are not important for sorting, you still have to choose an arbitrary but consistent ordering if you don't want them to be ignored for the purposes of duplicates.

The key consistency you need to ensure is compare(a, b) == -compare(b, a) or more accurately sign(compare(a, b)) == -sign(compare(b, a))

like image 199
Peter Lawrey Avatar answered Jan 31 '23 09:01

Peter Lawrey


TreeMap compare keys using comparator.

Your comparator return 0 for two keys with same weight. So from TreeMap perspective such keys are equal.

like image 27
talex Avatar answered Jan 31 '23 09:01

talex