1

I want to create a top 5 list of unique key value pairs sorted according to a value.

I have tried creating a Hashmap but since the original list that i read from JSON is sorted Hashmap overwrites the last value so they key will have the smallest value instead of the largest.

The solution was to use LinkedHashSet, to ensure uniqueness and keep the order. But since i am storing a key, value pairs i decided to create a new class and save them as objects.

I know that i had to implement comparable but apparently there is no comparison happening and the LinkedHashSet is not unique.

My Code is:

public class cellType implements Comparable<Object> {

private String type;
private double confidence;

@Override
public String toString() {
    return "type=" + type + " - confidence=" + confidence ;
}

public cellType(String type, double confidence) {
    super();
    this.type = type;
    this.confidence = confidence;
}
public String getType() {
    return type;
}
public void setType(String type) {
    this.type = type;
}
public double getConfidence() {
    return confidence;
}
public void setConfidence(double confidence) {
    this.confidence = confidence;
}
@Override
public boolean equals(Object obj) {
    if (!(obj instanceof cellType)) {
          return false;
        }
    cellType ct = (cellType) obj;
    return type.equals(ct.getType());
}
@Override
public int compareTo(Object o) {
    cellType ct = (cellType) o;
    return type.compareTo(ct.getType());
}

}

    public static void main(String args[]) throws IOException, JSONException {
    String freebaseAddress = "https://www.googleapis.com/freebase/v1/search?query=";
    System.setProperty("https.proxyHost", "proxy");
    System.setProperty("https.proxyPort", "8080");
    JSONObject json = readJsonFromUrl(freebaseAddress + "apple");
    LinkedHashSet<cellType> rich_types = new LinkedHashSet<cellType>();
    JSONArray array = json.getJSONArray("result");
    for (int i = 0; i < array.length(); i++) {
        if (array.getJSONObject(i).has("notable")) {
            JSONObject notable = new JSONObject(array.getJSONObject(i)
                    .getString("notable"));
            if (rich_types.size() <= 5)
                rich_types.add(new cellType(notable.getString("name"), (Double) array.getJSONObject(i).get("score")));
        }
    }
    System.out.println(rich_types);
}

The output is:

[type=Monarch - confidence=79.447838, type=Monarch - confidence=58.911613, type=Monarch - confidence=56.614368, type=Founding Figure - confidence=48.796387, type=Politician - confidence=38.921349, type=Queen consort - confidence=36.142864]

AhmadAssaf
  • 3,556
  • 5
  • 31
  • 42
  • i have solved the issue by adding using a Hashmap and checking the Key doesn't exist, but i do not like this solution and i guess it should be solved more elegantly – AhmadAssaf Feb 27 '12 at 14:32

2 Answers2

1

You need to implement hashCode() too.
Anyone who even considers implementing equals() and hashCode() needs to read at least this chapter of Effective Java or better yet the whole book.

MK.
  • 33,605
  • 18
  • 74
  • 111
  • I think the OP wants to *sort* the keys, not sure hashCode will help. – Peter Lawrey Feb 27 '12 at 13:59
  • 1
    @PeterLawrey LinkedHashSet is not going to to sort anything. He does mention that he gets uniqueness violated. In any case the book talks about comparable as well so reading it will help. – MK. Feb 27 '12 at 14:02
  • as the original list is already sorted, i dont care about sorting at the moment, i care about the order. Thanks a lot for the link, i will check the book now. – AhmadAssaf Feb 27 '12 at 14:20
1

I think you mean you want to use TreeMap (Map not Set) to use Comparable keys to sort them. LinkedHashSet is a collection of elements which keep the order they were added.

It sounds like what you want is

if (rich_types.size() <= 5) {
    cellType ct = new cellType(notable.getString("name"), (Double) array.getJSONObject(i).get("score"));
    if(!rich_type.contains(ct))
        rich_types.add(ct);
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • with TreeMap i got the same behavior as HashMap, the value assigned to the key is overwritten, for the example above Monarch=56.614 .. instead of having the first highest value which is 7944 .. – AhmadAssaf Feb 27 '12 at 14:28
  • If your "type"s are the same, they will be treated as duplicates. If they are not duplicates, you need to give them different keys. If you need to allow duplicates, you can use a List instead. – Peter Lawrey Feb 27 '12 at 14:37
  • sorry i was not clear in my previous comment, they are recognized as duplicates and the list is unique now, but the value for the key is overwritten by the last duplicate value found .. and i do not wish to have that – AhmadAssaf Feb 27 '12 at 14:42
  • In which case you want duplicates or you want to keep the largest/smallest/total of values? – Peter Lawrey Feb 27 '12 at 14:49
  • i dont wish to have duplicates and i would like to keep the largest value (the first occurrence as they are already sorted) – AhmadAssaf Feb 27 '12 at 16:08