Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么在集合中使用比较器而不是equals()?_Java_Sorting_Comparator - Fatal编程技术网

Java 为什么在集合中使用比较器而不是equals()?

Java 为什么在集合中使用比较器而不是equals()?,java,sorting,comparator,Java,Sorting,Comparator,有一个JavaBean汽车可能包含两个值:model和price 现在假设我以这种方式重写equals()和hashcode()只检查模型: public boolean equals(Object o) { return this.model.equals(o.model); } public int hashCode() { return model.hashCode(); } List<Car> car = new ArrayLis

有一个JavaBean汽车可能包含两个值:model和price

现在假设我以这种方式重写equals()和hashcode()只检查模型:

public boolean equals(Object o) {            
    return this.model.equals(o.model);
}


public int hashCode() {
    return model.hashCode();
}
List<Car> car = new ArrayList<Car>();


car.add(new Car("carA",100f));
car.add(new Car("carB",101f));
car.add(new Car("carC",110f));

System.out.println(a.contains(new Car("carB",111f)));
这允许我检查arraylist是否已经包含同一型号的商品车(价格不重要),方法如下:

public boolean equals(Object o) {            
    return this.model.equals(o.model);
}


public int hashCode() {
    return model.hashCode();
}
List<Car> car = new ArrayList<Car>();


car.add(new Car("carA",100f));
car.add(new Car("carB",101f));
car.add(new Car("carC",110f));

System.out.println(a.contains(new Car("carB",111f)));
但现在有一个问题,它返回FALSE。。。为什么?

当我使用arrayList调用contains()时,似乎调用了equals()方法。 但是,当我使用带有比较器的树集调用contains()时,似乎使用了比较器


为什么会发生这种情况?

一个
TreeSet
是隐式排序的,它使用一个
比较器来进行排序。
equals()。只有
比较器才能做到这一点


更重要的是,
TreeSet
还使用比较进行搜索。这是基于树的地图/集合的整个点。调用
contains()
方法时,将执行二进制搜索,并根据比较器的定义找到或未找到目标。比较器不仅定义逻辑顺序,还定义逻辑标识。如果你依赖于一个不一致的<代码> >均衡器()/代码>实现所定义的逻辑身份,那么混乱可能会随之发生。

< P>不同行为的原因是,在比较方法中考虑价格成员,但忽略它。p>
new Car("carB",101f)     // what you add to the list   
new Car("carB",111f)     // what you are looking for

这两个实例都是“相等”(抱歉…),因为它们的模型成员是相等的(并且实现在该测试之后停止)。但是,它们“比较”是不同的,因为该实现还检查price成员。

TreeSet
形成一个二叉树,根据自然(或非自然)顺序保存元素,因此为了快速搜索,一个特定元素是集合,
TreeSet
使用
Comparable
Comparator
而不是
equals()

正如JavaDoc所指出的:

请注意,由集合维护的顺序(无论是否为显式 如果提供比较器,则必须与equals一致 正确实现Set接口。(见可比或比较) 对于一个与等于一致的精确定义。)这是如此 因为Set接口是根据equals操作定义的, 但是TreeSet实例使用其 比较法,所以两个元素被认为是相等的 用这种方法,从集合的观点来看,是相等的。这个 即使集合的顺序不一致,集合的行为也是定义良好的 平等;它只是没有遵守集合的总合同 接口

我们可以找到与HashCode/Equals合同的相似之处:

如果
equals()
返回
true
hashcode()
也必须返回true才能在搜索过程中找到

同样,对于
TreeSet

如果
contains()
(使用
Comparator
Comparable
)返回
true
equals()
也必须返回
true
,以便与
equals()
一致


因此:
TreeSet.equals()
方法中使用的字段必须与
Comparator
实现中使用的字段完全相同(不多也不少)。

在TreeSet javadoc中,我认为它说明了一切:“请注意,由集合维护的顺序(无论是否提供了显式比较器)如果要正确实现Set接口,必须与equals保持一致。“link:A
TreeSet
可能不是正确的数据结构。是的,equals()和compare()在bean中处理不同的值。但是调用contains()总是一样的,虽然返回的结果应该不同。虽然我自己尝试回答这个问题,而且我确实明白,原则上二进制搜索在导航树时必须进行比较,但我也有一些OP的困惑。具体来说,Javadoc声明
equals()
contains()
使用。你描述的“合同”记录在哪里?@1111我写道,因为它似乎完全符合逻辑。然而,我同意Javadoc并没有精确地定义它。我猜javadoc使用概念算法
o==null相当简单地解释了这个机制?e==null:o.equals(e)
而没有进入实际的实现细节。@111事实上,与
equals()
用法相关的奇怪句子只是指
Set
接口的
contains()
Javadoc。因此,如果需要一个只在“model”上工作的equals(),因此应该使用ArrayList而不是TreeSet,对吗?因为在这种情况下,与任何比较器都没有冲突:我可以将比较器传递给Collections.sort(),在这种情况下,它不在列表中。@user1883212,只要您以不同的方式定义
compareTo()
equals()
方法,您无法保证
TreeSet
行为的完美一致性。如果您真的无法更改这些方法(这是非常糟糕的…),那么是的,
ArrayList
将是首选,或者更好的
HashSet