5
\$\begingroup\$

I want to return a set of items with an attached score to the user so that the user can easily iterate from highest to lowest and get the n-th highest items.

Problems

  • The JavaDoc of SortedSet.first() says "Returns the first (lowest) element currently in this set.". However in this case it is actually the highest score. If I compare the other way around, however, the user needs to reverse the SortedSet in order to do this common use case.
  • If I only compare by score, the SortedSet can only have one item with the same score. However comparing by c strikes me as somehow arbitrary (not sure what I can do against that).
  • Two Items with the same URI should not exist, however that is not prevented when they have different scores.
import java.util.SortedSet;
import java.util.TreeSet;
public class Main
{
 static class Item<T extends Comparable<T>> implements Comparable<Item<T>>
 {
 double score;
 T c;
 public Item(double score, T c)
 {
 this.score=score;
 this.c=c;
 }
 @Override public int compareTo(Item<T> i)
 { 
 int x = -Double.compare(score, i.score);
 if(x==0) {x=c.<T>compareTo(i.c);} 
 return x;
 }
 }
 public static SortedSet<Item<String>> findItems()
 {
 SortedSet<Item<String>> items = new TreeSet<>();
 items.add(new Item<String>(0.3,"honey"));
 items.add(new Item<String>(0.7,"wolf"));
 items.add(new Item<String>(0.5,"monitor"));
 return items;
 }
 public static void main(String[] args)
 {
 // iterate from best to lowest score
 for(Item item: findItems()) {}
 // get item with best score
 findItems().first();
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 19, 2014 at 9:52
\$\endgroup\$
2
  • \$\begingroup\$ This question on StackOverflow might help: stackoverflow.com/questions/3040784/… . In your case, perhaps give each Item an incremental unique id? \$\endgroup\$ Commented Aug 19, 2014 at 10:15
  • \$\begingroup\$ For your first point, in the documentation, lowest is just an example for a typical collection of numbers sorted in ascending order. If you use a -Integer.compare(a,b) comparator, the lowest element would then be Integer.MAX_VALUE. \$\endgroup\$ Commented Aug 19, 2014 at 11:56

1 Answer 1

3
\$\begingroup\$

The JavaDoc of SortedSet.first() says "Returns the first (lowest) element currently in this set.". However in this case it is actually the highest score.

The definition of lowest and highest is determined by the comparator. If you put Integers in the sorted set, the first element will be the lowest, because the default comparator will be used. In your Item object however, you have a different definition of what is lower and higher:

@Override
public int compareTo(Item<T> i) { 
 int x = -Double.compare(score, i.score);
 if(x==0) {x=c.<T>compareTo(i.c);}
 return x;
}

Your elements are still ordered from lowest to highest as dictated by your comparison method: practically you defined 0.7 to be lower than 0.3, that's all. As you noticed yourself, if you drop the negative sign in int x = -Double.compare(score, i.score); you effectively switch the ordering.

If I compare the other way around, however, the user needs to reverse the SortedSet in order to do this common use case.

I'm wondering if you're aware of the .last() method. It seems that's what you're looking for.

By the way, you can also make a TreeSet sort items in reverse order, by constructing it like this:

SortedSet<Item<String>> items = new TreeSet<>(Collections.reverseOrder());

If I only compare by score, the SortedSet can only have one item with the same score. However comparing by c strikes me as somehow arbitrary (not sure what I can do against that).

I'm not really sure what you mean by that. Since c is a String, comparison will be alphabetic by default.


I recommend this writing style (I also renamed variables):

@Override
public int compareTo(Item<T> item) {
 int cmp = -Double.compare(score, item.score);
 if (cmp == 0) {
 return c.<T>compareTo(item.c);
 }
 return cmp;
}
answered Aug 19, 2014 at 15:57
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.