Search code examples
javasortedset

SortedSet not working as per documentation


I have two sample code below. please review them and help me to spot the mistake

SortedSet<String> names = new TreeSet<>();
names.add("ar");
names.add("aj");
names.add("ka");
names.add("ru");
names.add("ti");

System.out.println(names);
SortedSet<String> rangeView;
rangeView = names.subSet("ar", "ti");
System.out.println("flag is "+names.remove("ti"));
System.out.println(rangeView);
System.out.println(names);

The output here is perfectly fine. names.remove("ti"); return true and range view also includes the fromElement and excludes toElement

But if I store an Employee object in the sorted set the remove does not removes the element and also range view shows that fromElement is excluded and toElement is included

here is the code snippet

Employee emp1 = new Employee("aj", LocalDate.parse("2019-09-20"), "57764");
Employee emp2 = new Employee("ar", LocalDate.parse("2016-06-20"), "5324");
Employee emp3 = new Employee("ka", LocalDate.parse("2017-07-21"), "2809");
Employee emp4 = new Employee("ru", LocalDate.parse("2018-08-12"), "2765");
Employee emp5 = new Employee("ti", LocalDate.parse("2018-08-12"), "2762");

SortedSet<Employee> names = new TreeSet<>();
names.add(emp1);
names.add(emp2);
names.add(emp3);
names.add(emp4);
names.add(emp5);
System.out.println(names);
SortedSet<Employee> rangeView;
rangeView = names.subSet(emp3, emp1);
System.out.println("flag is "+names.remove(emp5));
System.out.println(rangeView);
System.out.println(names);

Employee class has name, date of hiring and emp id as fields. it implements Comparable interface and compareTo method compares on hireday and equals case is handled.

the compareTo method is pasted below:

@Override
public int compareTo(Employee second) {
    int compareFlag = this.getHireday().compareTo(second.getHireday());
    if(compareFlag!=0){
        return compareFlag;
    }
    return this.getEmpid().equals(second.getEmpid()) ? 1:-1;
}

The problem I am facing is:

  1. the remove method does not actually removes the object from names
  2. subSet excludes fromElement and includes toElement

Solution

  • Your compareTo method violates the general contract of a Comparable. Consider emp1 and emp2 in your example. emp1.compareTo(emp2) will return -1, but emp2.compareTo(emp1) will also return -1.

    You can fix this by comparing the ids instead of just checking they are equal, which should make your set work as expected:

    @Override
    public int compareTo(Employee second) {
        int compareFlag = this.getHireday().compareTo(second.getHireday());
        if (compareFlag != 0) {
            return compareFlag;
        }
        return this.getEmpid().compareTo(second.getEmpid()); // Here
    }