Search code examples
javaoopdictionarycomparable

How to use comparable on hashmap of class object property


I have a soccer table that I am trying to sort by games won.

I have a class that implements comparable and looks at the won property. This seems to return the correct value (1, -1 or 0).

class TeamStandings implements Comparable<TeamStandings>{
    protected int matchesPlayed = 0;
    protected int won = 0;
    protected int draw = 0;
    protected int loss = 0;
    protected int goalsScored = 0;
    protected int goalsConceded = 0;
    protected int goalDifference = 0;
    protected int points = 0;

    @Override
    public int compareTo(TeamStandings other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal

        //System.out.println(this.won + " " + other.won + " " + Integer.valueOf(this.won).compareTo(Integer.valueOf(other.won)));
        return Integer.valueOf(this.won).compareTo(Integer.valueOf(other.won));

    }
}

This sort function should return a sorted hashmap. The hashmap has the teamname as the key and an instance of the teamstandings class as the value.

private static HashMap sortByValues(HashMap map) { 
    List list = new LinkedList(map.entrySet());
    // Defined Custom Comparator here
    Collections.sort(list, new Comparator() {
        public int compare(Object o1, Object o2) {

            System.out.println(((Comparable) ((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue()));
            return ((Comparable) ((Map.Entry) (o1)).getValue())
                    .compareTo(((Map.Entry) (o2)).getValue());          
        }
    });

    // Here I am copying the sorted list in HashMap
    // using LinkedHashMap to preserve the insertion order
    HashMap sortedHashMap = new LinkedHashMap();
    for (Iterator it = list.iterator(); it.hasNext();) {
        Map.Entry entry = (Map.Entry) it.next();
        sortedHashMap.put(entry.getKey(), entry.getValue());
        //System.out.println(entry.getKey());
    } 
    return sortedHashMap;
}

The hashmap sortedtable, takes a string for the team name and a teamstandings class object that contains the games won, lost, etc.

For some reason I can't get the table to sort. It just stays in the unsorted order. I believe it's something to do with the sortbyvalues function at the collection.sort position.

Any ideas how I can use the won value in my class to sort the hashmap?

public void printTable(){

    Map<String, TeamStandings> sortedTable = sortByValues(this.table);

    System.out.println("Group: " + this.groupLetter);
    System.out.println("Team" 
            + "\t" + "MP"
            + "\t" + "W"
            + "\t" + "D"
            + "\t" + "L"
            + "\t" + "GS"
            + "\t" + "GC"
            + "\t" + "GD"
            + "\t" + "P");

    //Iterator<Map.Entry<String, TeamStandings>> iterator = this.table.entrySet().iterator() ;
    Iterator<Map.Entry<String, TeamStandings>> iterator = sortedTable.entrySet().iterator() ;

    while(iterator.hasNext()){
        Map.Entry<String, TeamStandings> team = iterator.next();
        System.out.println(team.getKey() 
                + "\t" + team.getValue().matchesPlayed
                + "\t" + team.getValue().won
                + "\t" + team.getValue().draw
                + "\t" + team.getValue().loss
                + "\t" + team.getValue().goalsScored
                + "\t" + team.getValue().goalsConceded
                + "\t" + team.getValue().goalDifference
                + "\t" + team.getValue().points);
    }
}

Thanks

Dave

Edit:

I think it's something to do with this code, as I printed the list entries and they are not sorted:

    List list = new LinkedList(map.entrySet());
    // Defined Custom Comparator here
    Collections.sort(list, new Comparator() {
        public int compare(Object o1, Object o2) {

            System.out.println(((Comparable) ((Map.Entry) (o1)).getValue()).compareTo(((Map.Entry) (o2)).getValue()));
            return ((Comparable) ((Map.Entry) (o1)).getValue())
                    .compareTo(((Map.Entry) (o2)).getValue());          
        }
    });

I changed my code back to that which I originally posted and it was nothing to do with LinkedList or LinkedHashMap, the code actually worked all along, it was just sorting in ascending order. Which for a soccer league table is obviously not correct.

Edit:

The fix was adding the * -1 shown here:

return Integer.valueOf(this.won).compareTo(Integer.valueOf(other.won)) * -1;

Thanks to @Justin and @falsarella.


Solution

  • Apparently, as @Justin commented, the output is sorted, but in ascendant order:

    0, 1, 2, 3

    If you want that in descendant order, just change the returned integer sign from the compareTo method:

    return Integer.valueOf(this.won).compareTo(Integer.valueOf(other.won)) * -1;