在java中使用自然顺序和treeset

时间:2014-03-07 17:14:18

标签: java

我得到了一个意想不到的输出。请看一看。我无法找到问题所在。我的计划有什么问题?谁能解释一下?我得到了输出

    Joe     Sue     Mike      Clare   Juliet       
    Joe         Mike        Clare        Juliet
使用TreeSets界面,TreeMapsCollections.sort()以及Lists Comparable中的对象。

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);
        }
    }

}

3 个答案:

答案 0 :(得分:7)

您正在通过名称的长度比较这些人。名称“Joe”和“Sue”具有相同的长度。因此,TreeSet中只能出现其中一个。但是,此比较标准 equals的实现不一致!

您应将Person个对象放入列表中,并使用Collections#sort对此列表进行排序 - 最好使用自己的Comparator。另请参阅https://stackoverflow.com/a/21659849

编辑:进一步解释:

Set只能包含一次的每个元素。通过指定compareTo方法的方式,您实现了“Sue”和“Joe”相等(因为它们的名称长度相等)。因此,它们不能同时出现在Set中。

注意:基于equals方法,它们并不完全相同。但TreeSet使用compareTo方法,而此compareTo方法目前与equals不一致。因此Set因错误的compareTo方法而显示错误的行为。

编辑:可能的解决方案:

如果名称长度相等,您可以按字母顺序进行比较。这样,compareTo方法变得与equals 一致:当且仅当名称相等时,它才会返回0.

@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);
    }
}

答案 1 :(得分:1)

如果可以将元素添加到Set,则SortedSet使用compareTo进行评估。您的输入包含两个长度相同的名称(您的比较标准),因此必须过滤掉Joe或Sue中的一个(在您的情况下为Sue)。

答案 2 :(得分:0)

TreeSet文档讨论了(非强制)compareTo实现与equals一致的实现。在你的情况下,'Joe'和'Sue'的长度相等,根据你的compareTo实现,它们是相同的。一种解决方法是比较compareTo方法中的哈希码值,如果它们的长度相等。