Question

I am trying to understand the tree set . Why below code is only printing

a not b and c.

Below is the code:

Set<Person> tr = new TreeSet<Person>();

    tr.add(new Person("a",1));
        tr.add(new Person("c",7));
        tr.add(new Person("5",5));

        Iterator itr = tr.iterator();
        while(itr.hasNext())
        {

            Person person = (Person) itr.next();
            System.out.println(person.getName());
        }

Person Class

package com.set;

public class Person implements Comparable<Person>{

    private String name;

    private int age;


    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Person(String name , int age) {
        this.name= name;
        this.age = age;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {

            if(age > o.getAge() )
            {
                return 0;
            }else{
                return 1;
            }

    }


}
Was it helpful?

Solution

For sorting by age you need to take in account the both directions it can differ. Also, to keep compareTo() consistent with equals you should take in account the names too, if the ages are same.

@Override
public int compareTo(Person o) {
    int ret = age - o.getAge();
    if (ref == 0) {
        return name.compareTo(o.getName());
    }
    return ret;
}

@Override
public boolean equals(Object o) {
    if (o instanceof Person) {
        Person p = (Person) o;
        return p.getAge() == age && p.getName().equals(name);
    }
    return false;
}

OTHER TIPS

This is a correct code. To use a TreeSet your Person class has to implement the Comparable interface (it will not compile otherwise). If your code is not printing all the elements, it means, that you have implemented the compareTo method in a way, that all there Person objects are treated as one, so

 (new Person("a",1)).compareTo(new Person("c",7)) == 0
 (new Person("a",1)).compareTo(new Person("5",5)) == 0

if for example, you would like Person to be identified by their name (String object), this could be written as

public class Person implements Comparable<Person>{
    String name;
    int age;
    private Person(String name, int age) {
        this.name=name;
        this.age=age;
    }

    private String getName() {
        return name;
    }

    @Override
    public int compareTo(Person o) {
        return name.compareTo(o.name);
    }
}

which prints out

5
a
c

if you would like whole data pair to be used as an identifier, then it would be more reasonable to use HashSet (as it requires only to define when objects are equal, while TreeSet as an ordered data structure requires some kind of ordering, that you declare with compareTo method.

The problem is with your compareTo method:

@Override
public int compareTo(Person o) {

        if(age > o.getAge() )
        {
            return 0;
        }else{
            return 1;
        }

}

TreeSet uses compareTo() used to decide the equality of objects. And your implementation of compareTo will return 0 in all the cases when the new object age is greater than the existing element.

Return 0 from your compareTo() only if age of both objects is equal

@Override

public int compareTo(Person o) {

    if(age == o.getAge() )
    {
        return 0;
    }else{
        return 1;
    }

}

Problem is with your comapreTo method ,modify like this

@Override
public int compareTo(Person o) {

    if(age == o.getAge() )
    {
        return 0;
    }else if(age>o.getAge(){
        return 1;
    }else{
        return -1;
    }
}

according to java docs

comapreTo() method Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top