Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using Natural order with treeset in java

Tags:

java

I am getting an unexpected output for this. Please have a look. I am not able to find the problem. What's wrong with my program? Can anybody explain? I am getting the output

    Joe     Sue     Mike      Clare   Juliet       
    Joe         Mike        Clare        Juliet

objects in TreeSets and TreeMaps and with Collections.sort() for Lists, using the Comparable Interface.

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

class Person implements Comparable<Person> {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Person other = (Person) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    @Override
    public int compareTo(Person person) {
        int len1 = name.length();
        int len2 = person.name.length();

        if(len1 > len2) {
            return 1;
        }
        else if(len1 < len2) {
            return -1;
        }
        else {
            return 0;
        }
    }
}

public class App {

    public static void main(String[] args) { 

        List<Person> list = new ArrayList<Person>();
        SortedSet<Person> set = new TreeSet<Person>();


//adding  Element
        addElements(list);
        addElements(set);


//sorting element 
        Collections.sort(list);

//displaying result 
        showElements(list);
        System.out.println();
        showElements(set);
    }


//adding element methods

    private static void addElements(Collection<Person> col) {
        col.add(new Person("Joe"));
        col.add(new Person("Sue"));
        col.add(new Person("Juliet"));
        col.add(new Person("Clare"));
        col.add(new Person("Mike"));
    }

    private static void showElements(Collection<Person> col) {
        for(Person element: col) {
            System.out.println(element);
        }
    }

}
like image 813
sanjaybrandtest1 Avatar asked Mar 21 '26 22:03

sanjaybrandtest1


1 Answers

You are comparing the persons by the length of their names. And the names "Joe" and "Sue" have the same length. So only one of them can occur in the TreeSet. However, this comparison criterion is not consistent with the implementation of equals!

You should place your Person objects into a list, and sort this list with Collections#sort - preferably, with an own Comparator. Also see https://stackoverflow.com/a/21659849

EDIT: Further explaination:

A Set can contain each element only once. And by the way that you specified your compareTo method, you impled that "Sue" and "Joe" are equal (because their names have equal lengths). So they can not both appear in a Set.

Note: They are not really equal, based on the equals method. But the TreeSet uses the compareTo method, and this compareTo method is currently not consistent with equals. So the Set shows a wrong behavior because of your wrong compareTo method.

EDIT: A possible solution:

If the names have equal lengths, you can compare them alphabetically. This way, the compareTo method becomes consistent with equals: It will return 0 if and only if the names are equal.

@Override
public int compareTo(Person person) {
    int len1 = name.length();
    int len2 = person.name.length();

    if(len1 > len2) {
        return 1;
    }
    else if(len1 < len2) {
        return -1;
    }
    else {
        return name.compareTo(person.name);
    }
}
like image 135
Marco13 Avatar answered Mar 23 '26 13:03

Marco13



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!