TreeSet 在内部使用 TreeMap,因此在使用 Treeset 时是否需要实现 Hashcode 方法



我想知道当javadocs for TreeSet说是什么意思

此类实现由树状图实例支持的 Set 接口?

在下面的示例中,我还没有实现 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);
}
}

本示例打印[Tom Ben, Tom jon, Tom Wik] 。因此,它是基于compareTo方法进行排序的,在这种情况下hashcode()方法看起来微不足道。但是,Treeset由树状图支持,因此在内部,如果TreeMap用于排序,TreeMap如何对对象进行哈希处理?

我想你提出了两个问题。

1,为什么你的代码有效?

正如 Avi 在这个主题上所写:

当你不重写 hashCode() 方法时,你的类会从 Object 继承默认的 hashCode() 方法,它为每个对象提供不同的哈希代码。这意味着 t1 和 t2 有两个不同的哈希码,即使您比较它们,它们也会相等。根据特定的哈希图实现,地图可以自由地单独存储它们。

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

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

我的输出如下:

true
true
true
false
false
false
false
false
false

这意味着他们中的一些人在那里,其中一些人没有。

2,当 javadocs for Treeset 说"这个类实现了 Set 接口,由树状图实例支持"时,这意味着什么?

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

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.

这意味着在 TreeSet 类下有一个映射,并且有很多方法只委托给它。

我希望我能提供帮助。

TreeSet 内部确实使用 TreeMap。树状图不需要为关键对象实现哈希代码和等于方法。树状图内部使用红黑树,这是一个自平衡的二叉搜索树。此树中的顺序通过使用 compareTo 方法(键对象实现可比较接口)或比较方法(假设在构造树图时定义了比较器,在本例中实际上是 TreeSet)来维护。希望它能清除。

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

set.add(x);

内部调用树状图的 put 方法:

public boolean add(E e) {
    return m.put(e, PRESENT)==null;
}

现在,如果提供了比较器,则在内部调用放置方法,或者在您的情况下使用ComparisonLogic类"compareTo"方法。

它从不使用等于或哈希码显式使用,而是使用 compareTo(Object o1)(在实现 Comparable 时提供)或 compare(Object o1,object o2)(在实现 Comparator 时提供)方法来确定集合中是否存在 Object。

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

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

最新更新