konsolas
konsolas

Reputation: 1091

Objects disappearing from Java TreeSet

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

Answers (3)

John Bollinger
John Bollinger

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 the Set interface is defined in terms of the equals operation, but 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.

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

T. Claverie
T. Claverie

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

Joachim Sauer
Joachim Sauer

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

Related Questions