compareTo和equals在PriorityQueues中

| 我对所有\\“如果c在S上强加的顺序与equals不一致,则排序集(或排序映射)的行为会很奇怪。” Javadoc中的警告。 我什至不确定我是否需要PriorityQueue ... 我的情况是这样的: 我有一个带有整数时间戳和一些其他字段的类Event。 我正在寻找一个数据结构,可以在其中插入这些事件并按时间戳对事件进行排序。 不同的事件可以具有相同的时间戳,因此-如果我理解正确的话-compareTo和equals将不一致。 我的第一种方法是让Event实现Comparable并提供compareTo,如下所示: public int compareTo(Event e){   返回this.timestamp-e.getTimestamp(); } 我不知道该如何解决这个问题。我曾考虑过创建一个自定义比较器,但是在比较器的javadoc中也会弹出有关奇怪行为的警告。 我不想插入一个事件的多个相等的实例,我只希望它们按时间戳排序。 在此先感谢您的帮助 :) 编辑: 我只希望按时间戳对事件进行排序。两个不同的事件具有相同的时间戳很可能是。所以compareTo将返回0,因为它们具有相同的时间戳并且对于排序而言是相等的。但是equals()不会返回true,因为它们是不同的事件。 我不确定,使用PriorityQueue是否正确。我查看了SortedSet,但是它对compareTo和equals的一致性也有相同的警告。 也许我从错误的角度解决了这个问题,我不知道...     
已邀请:
不同的事件可以具有相同的时间戳      并按时间戳对事件进行排序 后者的要求尚不清楚。 Collection的迭代器是否应按排序顺序返回实例?还是该集合(如果在循环中为“ 0”,则应按排序顺序返回其以前的内容)?
iterator()
按顺序返回元素
PriorityQueue
不是这种情况。您可以使用
SortedSet
,但是那些要求排序顺序与equals保持一致,正如您正确指出的那样,您无法实现。据我所知,在JDK中,没有“ 4”将其元素保持在排序顺序中,从而认为某些元素相等。但是,您可以使用数组或
ArrayList
,并在更改后使用
Arrays.sort
或ѭ7changes对其进行手动排序。如果集合更改很少,那么我会选择这种方法。如果它经常更改,那么您将不得不超越JDK或自己实现数据结构。
poll()
按排序顺序返回元素 这就是优先级队列的优点。
PriorityQueue
不需要require10ѭ(或implementation11 implementation的实现)与等式保持一致;其JavaDoc明确写道:   就指定的顺序而言,此队列的头是最小的元素。如果多个元素的价值最小,那么头就是那些元素之一-领带被任意打破。 此外,JDK 6中的
PriorityQueue
实现仅使用
equals
来实现
indexOf(E)
contains(Object)
和ѭ16neither,它们都不以任何方式使用比较器。因此,对于这
Collection
,确实没有一种方法可以使与equals保持一致。 可比与比较器 请注意,就实现与equals的一致性而言,是否实现Comparable或Comparator都没有关系。对于
SortedSet
,两个都必须等于等号;对于
PriorityQueue
Collection.sort
Arrays.sort
,两个都不必相等。
TreeSet
,与with13ѭ一致 解除评论:   
TreeSet
是SortedSet,并且明确声明仅依赖compareTo / compare。它明确表示:“即使集合的顺序与equals不一致,集合的行为也是明确定义的;它只是无法遵守Set接口的常规协定。” 如果您引用,请引用所有相关部分。全文如下:   请注意,如果要正确实现“ 25”接口,则集合(无论是否提供显式比较器)所维护的顺序必须与equals一致。 [...]之所以这样,是因为
Set
接口是根据
equals
操作定义的,但是
TreeSet
实例使用其
compareTo
(或
compare
)方法执行所有元素比较,因此被该方法视为相等的两个元素是:从集合的角度来看,相等。即使集合的顺序与equals不一致,它的行为也是定义明确的。它只是不遵守
Set
接口的一般约定。 所以是的,它的定义很明确,但是并没有满足问题的要求:如果您将
TreeSet.add
Event
传递给时间戳,而时间戳中的时间戳与集合中的另一个
Event
相同,则新的
Event
将被视为重复项而不会添加,即使33英镑不是37英镑。问题询问如何对ѭ4进行排序;那不应该消除重复排序键的“ 39”,应该吗?     
           如果c对S施加的排序与equals不一致,则排序后的集合(或排序后的映射)将表现异常。 那仅意味着当且仅当
e1.equals(e2)
然后
e1.compareTo(e2) == 0
。 而且,当且仅当
!e1.equals(e2)
,然后
e1.compareTo(e2) != 0
。 这就是使两种方法保持一致所要做的。 因此,通过实现compareTo的方式,您还应该将equals()重写为:
@Override
public boolean equals(Event e) {
    return this.timestamp.equals(e.timestamp);
}
注意:我不知道时间戳的数据类型,但是如果它是原始类型,则将
==
而不是
equals()
用作替代方法。     
        当实现
Comparable
时,还应该覆盖
equals(Object)
,因为只有当
equals
返回true时,
compareTo
才应返回零。   仅当equals(Object)返回true时,compareTo(T)才应返回零。 不仅如此。由于签订了另一份合同,您应/必须重写
equals
时,应重写
hashCode()
。   相等的对象必须具有相等的哈希码。
public class Event implements Comparable<Event> {

    private long timestamp;

    public long getTimestamp() {
        return this.timestamp;
    }

    @Override
    public int compareTo(Event o) {
        return (this.timestamp < o.timestamp ? -1
                : (this.timestamp == o.timestamp ? 0 : 1));
    }

    @Override
    public int hashCode() {
        return (int) (this.timestamp ^ (this.timestamp >>> 32));
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Event) {
            return this.timestamp == ((Event) obj).timestamp;
        }

        return false;
    }

}
compareTo
equals
hashCode
的实现取自
java.lang.Long
中的实现。您还可以通过Eclipse之类的IDE生成这些方法。 如果要使equals必须返回false(如另一条评论中所述)的evals等于0,则必须实现一个Comparator而不是Comparable。
public class EventComparator implements Comparator<Event>, Serializable {

    private static final long serialVersionUID = 1L;

    @Override
    public int compare(Event o1, Event o2) {
        return (o1.getTimestamp() < o2.getTimestamp() ? -1
                : (o1.getTimestamp() == o2.getTimestamp() ? 0 : 1));
    }

}
    

要回复问题请先登录注册