Java TreeSet在内部使用TreeMap,所以在使用TreeSet时是否需要实现Hashcode方法?

Java TreeSet在内部使用TreeMap,所以在使用TreeSet时是否需要实现Hashcode方法?,java,collections,hashcode,treemap,treeset,Java,Collections,Hashcode,Treemap,Treeset,我想知道TreeSet的javadocs说 这个类实现了Set接口,由一个TreeMap实例支持 在下面的示例中,我没有实现Hashcode方法,它仍然按照预期工作,即它能够对对象进行排序。请注意,我故意没有实现一致的Equals实现来检查TreeSet行为 import java.util.TreeSet; public class ComparisonLogic implements Comparable<ComparisonLogic>{ String field1; S

我想知道
TreeSet
的javadocs说

这个类实现了Set接口,由一个TreeMap实例支持

在下面的示例中,我没有实现
Hashcode
方法,它仍然按照预期工作,即它能够对对象进行排序。请注意,我故意没有实现一致的
Equals
实现来检查
TreeSet
行为

import java.util.TreeSet;


public class ComparisonLogic implements Comparable<ComparisonLogic>{

String field1;
String field2;

public String toString(){
    return field1+" "+field2;
}

ComparisonLogic(String field1,String field2){
    this.field1= field1;
    this.field2= field2;

}
public boolean equal(Object arg0){
    ComparisonLogic obj = (ComparisonLogic) arg0; 

    if(this.field1.equals(obj.field1))
        return true;
    else
        return false;
}

public int compareTo(ComparisonLogic arg0){
    ComparisonLogic obj = (ComparisonLogic) arg0;   
    return this.field2.compareToIgnoreCase(obj.field2);
}

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub

    ComparisonLogic x = new ComparisonLogic("Tom", "jon");
    ComparisonLogic y = new ComparisonLogic("Tom", "Ben");
    ComparisonLogic z = new ComparisonLogic("Tom", "Wik");

    TreeSet<ComparisonLogic> set = new TreeSet<ComparisonLogic>();
    set.add(x);
    set.add(y);
    set.add(z);
    System.out.println(set);
}

}
import java.util.TreeSet;
公共类比较逻辑实现可比较{
字符串字段1;
字符串字段2;
公共字符串toString(){
返回字段1+“”+field2;
}
比较逻辑(字符串字段1、字符串字段2){
这个。field1=field1;
这个.field2=field2;
}
公共布尔相等(对象arg0){
ComparisonLogic obj=(ComparisonLogic)arg0;
如果(此字段1等于(对象字段1))
返回true;
其他的
返回false;
}
公共int比较对象(比较逻辑arg0){
ComparisonLogic obj=(ComparisonLogic)arg0;
返回此.field2.compareTignoreCase(对象字段2);
}
/**
*@param args
*/
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
ComparisonLogic x=新的ComparisonLogic(“汤姆”、“乔恩”);
ComparisonLogic y=新的ComparisonLogic(“汤姆”、“本”);
ComparisonLogic z=新的ComparisonLogic(“Tom”、“Wik”);
树集=新树集();
增加(x);
设置。添加(y);
设置。添加(z);
系统输出打印项次(套);
}
}

此示例打印
[汤姆·本、汤姆·乔恩、汤姆·维克]
。因此,它是基于
compareTo
方法和
hashcode()
方法进行排序的,在这种情况下,该方法看起来无关紧要。但是,
Treeset
是由TreeMap支持的,因此在内部,如果
TreeMap
用于排序,那么
TreeMap
如何对对象进行散列?

您的
ComparisonObject
正在使用
对象上定义的
hashCode
方法。尝试添加多个不同的
ComparisonLogic
,两个字段的值相同,然后看看会发生什么。

我认为您提出了两个问题

1,您的代码为什么工作?

正如在主题中所写:

当您不重写hashCode()方法时,您的类将从Object继承默认的hashCode()方法,这将为每个对象提供一个不同的哈希代码。这意味着t1和t2有两个不同的散列码,即使要比较它们,它们也是相等的。根据特定的hashmap实现,映射是免费的,可以单独存储它们

这意味着它不必单独存储它们,但也可以。请尝试以下代码:

TreeSet<ComparisonLogic> set = new TreeSet<ComparisonLogic>();
    set.add(new ComparisonLogic("A", "A"));
    set.add(new ComparisonLogic("A", "B"));
    set.add(new ComparisonLogic("A", "C"));
    set.add(new ComparisonLogic("B", "A"));
    set.add(new ComparisonLogic("B", "B"));
    set.add(new ComparisonLogic("B", "C"));
    set.add(new ComparisonLogic("C", "A"));
    set.add(new ComparisonLogic("C", "B"));
    set.add(new ComparisonLogic("C", "C"));
    set.add(new ComparisonLogic("A", "A"));

    System.out.println(set.remove(new ComparisonLogic("A", "A")));
    System.out.println(set.remove(new ComparisonLogic("A", "B")));
    System.out.println(set.remove(new ComparisonLogic("A", "C")));
    System.out.println(set.remove(new ComparisonLogic("B", "A")));
    System.out.println(set.remove(new ComparisonLogic("B", "B")));
    System.out.println(set.remove(new ComparisonLogic("B", "C")));
    System.out.println(set.remove(new ComparisonLogic("C", "A")));
    System.out.println(set.remove(new ComparisonLogic("C", "B")));
    System.out.println(set.remove(new ComparisonLogic("C", "C")));
这意味着有些人在那里,有些人不在

2,当javadocsfortreeset说“这个类实现了Set接口,由一个TreeMap实例支持”,这意味着什么?

这意味着java 1.7中的TreeSet类如下所示:

true
true
true
false
false
false
false
false
false
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
/**
 * The backing map.
 */
private transient NavigableMap<E,Object> m;

 TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
}

... (lots of other code)     

public boolean contains(Object o) {
    return m.containsKey(o);
}

etc.
公共类树集扩展了抽象集
实现NavigableSet、Cloneable、java.io.Serializable
{
/**
*背景地图。
*/
私人临时导航地图m;
TreeSet(NavigableMap m){
这个,m=m;
}
…(许多其他代码)
公共布尔包含(对象o){
返回m.containsKey(o);
}
等
这意味着TreeSet类下面有一个映射,并且有很多方法只被委托给它


我希望我能提供帮助。

TreeSet内部使用TreeMap对象“m”将对象存储为键值对,这意味着调用

set.add(x);
内部调用TreeMap的put方法:

public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}
现在,put方法在内部调用Comparator(若提供了Comparator),或者在您的示例中使用ComparisonLogic类“compareTo”方法

它从不显式使用equals或hashcode,而是使用compareTo(对象o1)(在实现Comparable时提供)或compare(对象o1,对象o2)(在实现Comparator时提供)方法来确定集合中是否存在对象


所以,要回答您的问题,不需要实现hashcode()方法,除非您在比较中使用它(compare或compareTo)方法实现。

确实TreeSet在内部使用TreeMap。TreeMap不需要为关键对象实现hashCode和equals方法。TreeMap在内部使用红黑树,这是一个自平衡的二进制搜索树。此树中的顺序通过使用compareTo方法或compareTo方法来维护(关键对象实现了Compariable接口)或compare方法(前提是在构造TreeMap时定义了Compariator,在本例中是针对TreeSet的)。希望它会被清除。

无需更多信息-试试我的建议,你就会明白我的意思!我搞砸了。我的equals方法语法不正确。我使用了equal():(完美的答案!