2016-06-20 50 views
4

当我在看Java Object Ordering教程时,文章的最后一部分'比较器'让我困惑了一下。排序集合的Java对象排序

通过定义类别Employee,该类别本身可以通过员工姓名进行比较,本教程不会显示该类是否已覆盖equals方法。然后它使用定制的Comparator,其中员工按照资历进行排序以对员工列表进行排序,并且我可以理解。

然后教程解释了为什么这将不作为一个TreeSet收集整理等(一个SortedSet)工作,其原因是:

它产生的顺序不是与equals兼容。这意味着这个比较器等同于equals方法没有的对象。特别是,同一天雇用的任何两名雇员将相当于平等。当你对一个List进行排序时,这并不重要;但是当您使用比较器来订购已排序的集合时,这是致命的。如果使用此比较器将同一日期雇用的多个雇员插入到TreeSet中,则只会将第一个雇员添加到该集合中;第二个将被视为重复的元素,将被忽略。

现在我很困惑,因为我知道List允许重复的元素,同时Set不基于equals方法。所以我想知道教程何时说由Comparator生成的顺序与等号不兼容,这是什么意思?而且它还说'如果您使用此比较器将同一日期雇用的多个员工插入到TreeSet中,则只会将第一个员工添加到该集合中;第二个将被视为重复的元素,将被忽略。“我不明白如何使用Comparator将影响使用原始equals方法。我认为我的问题是如何使用compare和方法生产和分类TreeSet

回答

3

所以我不知道教程是什么时候说比较器生成的顺序与equals不兼容,这是什么意思?

在此示例中,Comparator仅比较两个Employee对象。此比较不以任何方式使用equalshashCode。记住这一点,当我们将这个Comparator传递给TreeSet时,该集合将认为Comparator的任何结果都是0。因此,如果有任何Employee共享开始日期,则只会添加一个,因为该集合认为它们是平等的。

最后:

我想我的问题是,如何TreeSet中会产生在这种情况下排序,当比较和等于使用方法。

对于TreeSet,如果Comparator给出,它使用compare方法来确定对象的平等和订货。如果没有给出Comparator,那么该集合使用正在排序的对象的compareTo方法(它们必须实现Comparable)。

为什么Java规范声称,正在使用必须符合equalscompare/compareTo方法是因为Set规范利用了equals,即使这种特定类型的Set,在TreeSet,使用比较,而不是原因。

如果您从某种方法实施中收到Set,则可以预计equals方法定义的Set中没有对象的重复项。因为TreeSet不使用此方法,所以开发人员必须小心确保比较方法与equals的结果相同。

+0

谢谢!现在我明白这是为了保持它与'Set'接口的一致性,并且我看到了使用'equals()'方法的'contains()'方法。 –

2

TreeSet仅使用比较器,以确定是否两个元素“相等”:

https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html

。注意,通过一组(无论是否提供了明确的比较器)维持的顺序必须如果要正确实现Set接口,请与equals保持一致。 (请参阅Comparable或Comparator以获得与equals一致的精确定义。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,所以两个从这个方法看,被这个方法认为是相等的元素是相等的。 即使排序与等号不一致,集合的行为也是明确定义的;它只是不服从Set接口的总体合同。

这意味着比较应该返回0,当且仅当equals返回true,让TreeSet中和其他集之间的一致的行为,像HashSetHashSet确实使用equals和散列码来确定两个元素是否“相等”。

+0

我没有完全得到你的答案,直到锆石详细阐述它。不过,非常感谢。 –