Java 将非基本对象添加到树集时,重写hashCode和等于必须吗?

Java 将非基本对象添加到树集时,重写hashCode和等于必须吗?,java,treeset,Java,Treeset,为了更好地理解自然排序,我将遵循一个教程,使用TreeSet和类似的界面 本教程告诉我,要将非基本自定义对象添加到集合中,我需要实现equals()和hashCode()。然而,即使没有实现这些方法,我也能够编译和运行代码(如下所示)。我将IntelliJ与Java8一起使用 在使用TreeSet(SortedSet接口)和自然排序时,是否绝对需要重写equals()和hashCode() class My_Person implements Comparable<My_Person>

为了更好地理解自然排序,我将遵循一个教程,使用TreeSet和类似的界面

本教程告诉我,要将非基本自定义对象添加到集合中,我需要实现
equals()
hashCode()
。然而,即使没有实现这些方法,我也能够编译和运行代码(如下所示)。我将IntelliJ与Java8一起使用

在使用TreeSet(SortedSet接口)和自然排序时,是否绝对需要重写
equals()
hashCode()

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

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

    public String toString() {
        return name;
    }

//    @Override
//    public boolean equals(Object o) {
//        if (this == o)
//            return true;
//        if (o == null || getClass() != o.getClass())
//            return false;
//        My_Person my_person = (My_Person) o;
//        return Objects.equals(name, my_person.name);
//    }
//
//    @Override
//    public int hashCode() {
//        return Objects.hash(name);
//    }

    @Override
    public int compareTo(My_Person person) {
        return name.compareTo(person.name);
    }
}

public class NaturalOrdering {

    public static void main(String[] args) {

        List<My_Person> list = new ArrayList<>();
        Set<My_Person> set = new TreeSet<>();   

        addElement(list);
        addElement(set);

        Collections.sort(list);

        showElement(list);
        System.out.println("\n");
        showElement(set);

    }


    private static void addElement(Collection<My_Person> collection) {
        collection.add(new My_Person("Joe"));
        collection.add(new My_Person("Sue"));
        collection.add(new My_Person("Juliet"));
        collection.add(new My_Person("Clare"));
        collection.add(new My_Person("Mike"));
    }


    private static void showElement(Collection<My_Person> collection) {
        for(My_Person element: collection) {
            System.out.println(element);
        }
    }
}
class My_Person实现可比较{
私有字符串名称;
公共My_Person(字符串名称){
this.name=名称;
}
公共字符串toString(){
返回名称;
}
//@覆盖
//公共布尔等于(对象o){
//if(this==o)
//返回true;
//如果(o==null | | getClass()!=o.getClass())
//返回false;
//我的人我的人=(我的人)o;
//返回Objects.equals(name,my_person.name);
//    }
//
//@覆盖
//公共int hashCode(){
//返回Objects.hash(name);
//    }
@凌驾
公共int比较(我的人){
返回name.compareTo(person.name);
}
}
公共级自然保护{
公共静态void main(字符串[]args){
列表=新的ArrayList();
Set=新树集();
附录(列表);
增件(套);
集合。排序(列表);
showElement(列表);
System.out.println(“\n”);
展示元素(套);
}
专用静态void addElement(集合){
收藏。添加(新的My_Person(“Joe”));
收藏。添加(新的My_Person(“Sue”));
收藏。添加(新的My_Person(“朱丽叶”);
收藏。添加(新的My_Person(“Clare”);
收藏。添加(新的My_Person(“Mike”));
}
私有静态void showElement(集合){
对于(My_Person元素:集合){
系统输出打印项次(元素);
}
}
}

这取决于您对平等的要求。如果不重写
equals
hashCode
,则两个对象定义为相等当且仅当它们相同时(即相同的对象)。如果需要其他相等定义,则必须重写这些方法

这不是“绝对必要的”,但如果不这样做,您可能会得到意外/错误的输出。因此,如果不覆盖它们,它有时可能仍然有效,但也可能失败。所以为了安全起见,最好把它盖上。
如果您需要检查相等性,它将失败。但若您只关心按照自己在compareTo方法中定义的逻辑对存储对象进行排序,那个么我认为并没有必要重写equals或hashcode

这不是TreeSet或任何集合所要求的。但布景本质上是独特对象的集合。对于基本类型,Java有办法知道两个对象是否相同。对于非原语用户,必须告诉Java如何知道两个对象是否相同,方法是重写
equals
hashcode
方法,方法调用这些方法来确定要添加的对象是否已经存在于集合中。因此,如果您需要集合中具有唯一功能的对象,则应该实现
equals
hashcode
方法。希望这有帮助。关于同一个话题

您有TreeSet的源代码(以及TreeSet在引擎盖下使用的TreeMap)。您可以清楚地看到TreeSet(和TreeMap)依赖于compareTo(),而不是hashCode()


另一方面,HashSet(以及HashSet在引擎盖下使用的HashMap)确实使用hashCode()和equals()。考虑到它们被命名为HashSet和HashMap,这并不奇怪。

根据Joshua Bloch在《有效Java》第3章中制定的规则,您应该始终覆盖对象的equals和hashcode。这一切都取决于您对像
新My_Person(“Joe”)这样的东西的期望。equals(新建My_Person(“Joe”))
返回。两个同名的人是否应该彼此相等?对象始终是非基本对象。因此使用术语“非基本对象”我认为总的来说,重写equals和hashCode比不重写更好、更安全。Thanks@Tiny我可能有点打错了,但你的陈述绝对没有任何价值!它是
HashSet
所要求的,因为Java8的
HashMap
在出现时使用自然顺序是散列冲突。这打破了一般合同,但事实确实如此。@chrylis我理解你的评论,我的回答对问题中提到的问题更为严格。但是,即使没有实现这些方法,我也能够编译和运行代码。因此,这是对为什么代码仍然编译和运行的解释。