我想知道TreeSet
的 javadocs 所说的含义
该类实现了由TreeMap实例支持的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
用于排序,TreeMap
如何对对象进行哈希处理?
答案 0 :(得分:7)
我认为你提出了两个问题。
1,为什么您的代码有效?
当您不覆盖hashCode()方法时,您的类从Object继承默认的hashCode()方法,该方法为每个对象提供不同的哈希代码。这意味着t1和t2有两个不同的哈希码,即使你要比较它们,它们也是相同的。根据特定的hashmap实现,地图 free 可以单独存储它们。
这意味着它不必单独存储它们,但它可能。试试这段代码:
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,当Treeset的javadocs说'这个类实现了由TreeMap实例支持的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类下面有一个映射,并且有很多方法只委托给它。
我希望我能提供帮助。
答案 1 :(得分:1)
TreeSet在内部使用TreeMap确实如此。 TreeMap不需要为关键对象实现hashCode和equals方法。 TreeMap内部使用Red-Black树,这是一种自平衡二叉搜索树。通过使用compareTo方法(关键对象实现Comparable接口)或比较方法(在构造TreeMap时定义比较器,在本例中实际为TreeSet)来维护此树中的顺序。希望它能够清除。
答案 2 :(得分:0)
您的ComparisonObject
正在使用hashCode
上定义的Object
方法。尝试添加许多不同的ComparisonLogic
,并为这两个字段添加相同的值,并查看会发生什么。
答案 3 :(得分:0)
TreeSet在内部使用TreeMap对象'm'将对象存储为键值对,这意味着调用
set.add(x);
内部调用TreeMap的put方法:
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
现在,如果提供了Comparator,或者在你的情况下使用ComparisonLogic类“compareTo”方法,put方法内部调用compare。
它从不显式使用equals或hashcode而是使用compareTo(Object o1)(在实现Comparable时提供)或compare(Object o1,object o2)(在实现Comparator时提供)方法来确定集合中Object的存在。 / p>
所以要回答你的问题,除非你在比较(compare或compareTo)方法实现中使用它,否则不需要实现hashcode()方法。