I'd like to have list of object sorted with property 'sort_1'. But when I want to remove I'd like it to use property 'id'. The following code represents the problem.
package javaapplication1;
import java.util.TreeSet;
public class MyObj implements Comparable<MyObj> {
public long sort_1;
public long id;
public MyObj(long sort, long id) {
this.sort_1=sort;
this.id=id;
}
@Override
public int compareTo(MyObj other) {
int ret = Long.compare(sort_1, other.sort_1);
return ret;
}
public String toString() {
return id+":"+sort_1;
}
public static void main(String[] args) {
TreeSet<MyObj> lst=new TreeSet<MyObj>();
MyObj o1 = new MyObj(99,1);
MyObj o2 = new MyObj(11,9);
lst.add(o1);
lst.add(o2);
System.out.println(lst);
MyObj o3 = new MyObj(1234, 1);
//remove myObje with id 1
boolean remove=lst.remove(o3);
System.out.println(lst);
}
}
Output of this code is:
[9:11, 1:99]
[9:11, 1:99]
I need to have list sorted as I do a lot of additions to the list. I don't want to explicitly use any 'sort' method. What are my options ?
EDIT:
My requirement is to have: objects with 'id' as unique but there can be object's with duplicate 'sort' value.
"a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal".
The TreeSet uses a self-balancing binary search tree, more specifically a Red-Black tree. Simply put, being a self-balancing binary search tree, each node of the binary tree comprises of an extra bit, which is used to identify the color of the node which is either red or black.
It uses compare() (or compareTo()) method to determine the equality of two elements.
Equal and EquivalentTwo sets A and B are equal if they have exactly the same elements. We write A = B. Two sets A and B are equivalent if n(A)= n(B). Another way of saying this is that two sets are equivalent if they have the same number of elements.
Just by chance I found this out yesterday as well. This seems to be an artifact of the implementation of TreeMap (which is what TreeSet uses to store its entries).
TreeMap uses a binary search tree for storing the key/value pairs, but it only ever uses the given Comparator (or the compare function if the key class implements Comparable) to check for equality, as you can see in this code exxcerpt:
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}
I'd almost call this a (not really fixable) bug since the JavaDoc of the Comparable interface explicitly says that returning 0 with the compareTo function does not have to imply "equalness":
It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)).
You won't be able to store stuff in the TreeSet the way you want it to. I'd recommend using a normal HashMap or a LinkedHashMap and then just sorting the output when you need to sort it with Collections.sort.
Besides all of this, I always find it strange to implement the Comparable interface. Most things don't really have a "natural" ordering that is immediately obvious. Sometimes this can lead to strange bugs (like this one!), so I typically always sort only when I need it using custom Comparators. Java 8 makes writing those really easy as well!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With