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():(完美的答案!