I have created a Student class like this:
public class Student implements Comparable {
private String firstName;
private String lastN
That is because TreeSet
uses compareTo
(or Comparator.compare
) to test whether two elements are equal. This is what the docs say about it.
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. (See Comparable or Comparator for a precise definition of consistent with equals.) 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. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
As java.util.TreeSet says:
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
Kudos to @Jon Skeet.
Since you have compared only first name in compareTo method, you need
@Override
public int compareTo(Student student) {
int comp = this.firstName.compareTo(student.firstName);
if(comp==0) return this.lastName.compareTo(student.lastName);
return comp;
}
when compareTo returns 0, treeSet assumes that its duplicate.
Well, your treeset key values are "A1","B1","A1","A2". Even though you are not overriding equals and hashcode still the default hashcode for "A1" will be same and hence the treeset will consider this key as duplicate key so you will not be able to enter "A1","B2"
Although question is quite old, but here is one very important point to understand which most people ignores while implementation.
TreeSet
does not compare the new element with all the existing elements in the Set
. It uses binary search technique. Therefore, If your input element is equal to an existing element (as per compareTo
contract) and same lies on the left side of tree
and your compareTo
method is implemented such a way that it forces your new element to lie on right side of tree
, your TreeSet
will not reject the new element even though same element is present inside it already (as per compareTo
contract). Lets see the following simple example.
I need to sort Item
s having properties as key
and priority
.
package com.manish;
import java.util.TreeSet;
public class Main {
static class Item implements Comparable<Item> {
private long key;
private int priority;
public Item(long key, int priority) {
super();
this.key = key;
this.priority = priority;
}
/*
* Items should be treated equal if Keys are equal.
* Higher priority item should be treated as greater item.
* If priorities are same, lower key value item should be
* treated as greater item.
*/
@Override
public int compareTo(Item o) {
if (this.key == o.key) {
return 0;
}
if (this.priority != o.priority) {
return this.priority - o.priority;
} else {
return this.key < o.key ? 1 : -1;
}
}
@Override
public String toString() {
return "Item [key=" + key + ", priority=" + priority + "]";
}
}
public static void main(String[] args) {
TreeSet<Item> set = new TreeSet<>();
set.add(new Item(2, 1));
set.add(new Item(4, 3));
set.add(new Item(3, 1)); //line 1
set.add(new Item(3, 2)); //line 2. Same item as Item(3,1)
while (!set.isEmpty())
System.out.println(set.pollFirst());
}
}
Output:
Item [key=3, priority=1]
Item [key=2, priority=1]
Item [key=3, priority=2]
Item [key=4, priority=3]
However, if you swap the line 1
and line 2
code, the output will get changed as below.
Item [key=2, priority=1]
Item [key=3, priority=2]
Item [key=4, priority=3]