Reputation: 1091
I have a class that I'd like to put in a TreeSet
, which implements Comparable
to sort them by priority. Here's a small segment:
public abstract class PacketListener implements Comparable<PacketListener> {
public enum ListenerPriority {
LOWEST, LOW, NORMAL, HIGH, HIGHEST
}
private final ListenerPriority priority; // Initialized in constructor
// ... class body ...
@Override
public final int compareTo(PacketListener o) {
return priority.compareTo(o.priority);
}
}
The idea is obviously for the TreeSet
to sort the objects by priority, allowing me to iterate through the listeners in order. However, I've discovered that, for some reason, I can't add a second PacketListener
to the set object. After adding two different PacketListener
objects, the size of the set remains at 1.
Should I not be using TreeSet
?
Upvotes: 2
Views: 764
Reputation: 180161
The API docs for TreeSet
contain this important information:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the
Set
interface. [...] This is so because theSet
interface is defined in terms of theequals
operation, but aTreeSet
instance performs all element comparisons using itscompareTo
(orcompare
) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal.
In other words, a TreeSet
can accommodate multiple instances of your PacketListener
class, but only so long as each has a different priority than all the others, so that for every pair of elements A and B, exactly one of these holds: either A == B
or A.compareTo(B) != 0
.
If you must accommodate multiple PacketListener
instances with the same priority in the same collection, then you need a different type of collection. HashSet
is perfectly good with classes that use the equals()
and hashCode()
methods inherited from Object
, provided that that is indeed the desired sense of instance equality. You could also consider a LinkedHashSet
if you want some kind of guarantee about iteration order, or maybe a PriorityQueue
if you want to order by priority but you are willing to use a different mechanism to avoid duplicates.
Upvotes: 7
Reputation: 12246
A Set
is a collection of unique elements. As you are using the priority to compare PacketListener
, I assume that there are at most five instances in you TreeSet
, one for each priority.
If the structure allows you, you can find a secondary key to compare PacketListener
, in case they have the same priority. If you can't, then TreeSet
is the wrong way to go.
Upvotes: 0
Reputation: 308021
TreeSet
treats two objects for which compareTo
returns 0 to be equals. Which means you'll can never have two objects with the same priority in your tree set with your current implementation.
On way to fix your problem is to make your compareTo
method consider all values that you care about (i.e. only objects that are actually equal return 0).
Upvotes: 1