spa*_*wal 5 java compare comparator
其实我经历在其中提到,当我们需要实现比较接口,我们可以覆盖equals方法教程之一(不过没有必要重写).
所以只是为了更好地理解
我重写方法如下
Test.java
import java.util.TreeSet;
public class Test
{
public static void main(String[] args)
{
TreeSet t = new TreeSet(new MyComparator());
t.add(1);
t.add(1);
t.add(2);
System.out.println(t);
}
}
Run Code Online (Sandbox Code Playgroud)
MyComparator.java
import java.util.Comparator;
public class MyComparator
implements Comparator
{
@Override
public int compare(Object o1, Object o2)
{
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i1.compareTo(i2);
}
@Override
public boolean equals(Object o1)
{
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
对于其他场景
import java.util.Comparator;
public class MyComparator
implements Comparator
{
@Override
public int compare(Object o1, Object o2)
{
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
return i1.compareTo(i2);
}
@Override
public boolean equals(Object o1)
{
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
现在无论我从equals方法返回的是true还是false ..它返回相同的treeset值.如果有人能够清除equals方法的功能性概念请
equals()在a上实现该方法Comparator允许您指示一个比较器提供与另一个比较器相同的顺序.它与元素的排序方式无关.它是一种非常先进且极少需要的功能.您极不可能遇到equals()实际调用比较器方法的情况.我建议你忽略它.
equals()类的方法,Comparator并且Comparator需要等于一致性,因为如果compareTo()和equals()方法没有返回一致的结果,一些 Java 集合类可能会表现得不可预测。
Java 使用 == 运算符来比较两个原语和/或检查两个变量是否引用同一个对象。例子 :
String apple1 = new String("apple");
String apple2 = new String("apple");
System.out.println(apple1.equals(apple2)); // true
StringBuilder app1 = new StringBuilder("apple");
StringBuilder app2 = new StringBuilder("apple");
System.out.println(app1.equals(app2)); // false
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我们得到了不同的行为。这是为什么?发生这种情况是因为 String 类实现了一个 equals() 方法,该方法检查值是否相同。另一方面,StringBuilder 没有实现 equals() 方法,而是使用Object类提供的 equals() 实现。由Object类提供(继承)的实现只是简单地检查两个引用的对象是否相同。
因此,要检查两个对象是否等效,Java 会使用该equals()方法,并且每当您引入自己的类型时,equals()如果您不想依赖方法的Object类实现,则必须覆盖该equals()方法
例如,让我们介绍我们自己的类型:简单类 Apple
public class Apple {
private int weight;
private int cost;
private String color;
Run Code Online (Sandbox Code Playgroud)
现在你将如何决定两个苹果是否相等?按颜色、重量、价格或其他什么?这就是为什么您需要明确提供您自己的 equals 方法,以便可以比较您的类型的对象是否相等。
下面的示例比较两个Apple对象是否相等,如果它们属于同一个“Apple”类并且它们的重量和成本相同,则表示两个对象相等。请注意,我们不按颜色进行比较,我们假设颜色在我们的案例中无关紧要,这意味着我们接受这样一个事实,即不同颜色但具有相同重量和相同成本的苹果被认为是相等的。
@Override
public boolean equals(Object obj) {
if ( !(obj instanceof Apple)) return false;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Apple other = (Apple) obj;
if (cost != other.cost and weight != other.weight )
return false;
return true;
}
Run Code Online (Sandbox Code Playgroud)
您可以为您的equals()方法实现您喜欢的任何逻辑。Javaequals()方法非常重要,它提供了开发者应遵循的契约或重要规则。我不会列出它们,你可以从这里得到它们,它们是合乎逻辑的并且非常直接。
还有另一个契约equals()- 每当您覆盖时equals(),您也应该覆盖hashCode()方法。这背后的原因是因为当对象作为键存储在映射中时,某些 Java 集合在内部使用哈希码。
哈希码是一个将对象分类的数字。想象一下,您收到各种苹果(红色、绿色、黄色),并在要求您提供特定种类时要求将它们归还。如果您对它们进行分类,将它们相应地放入不同的桶中,并在要求进行特定排序时(为简单起见,假设为红苹果),那么效率会更高,速度更快,并且由于您已经对它们进行了排序和分类,因此可以更快地检索它们. 希望现在清楚为什么您需要实施hashcode(). hashcode()有自己的合同或规则与equals()方法相同。他们几乎是常识:
首先,hashcode()同一程序内的结果不会改变。这意味着在你的hascode()计算中你不应该包括我在程序执行过程中改变的变量。例如,如果 Apple 的成本是可变的,即它可能会改变,那么将它们包含在 hashcode() 计算中并不是一个好主意,否则结果将不一致。
第二条规则说,当使用两个对象equals()调用hashCode()时,如果返回 true,则调用这些对象中的每一个都必须检索相同的结果。但是,如果equals()在使用两个对象调用时返回 false,则调用hashCode()这些对象中的每一个都不必返回不同的结果。令人困惑?为什么?因为hashCode()在对不等的对象调用时,结果不需要是唯一的 - 您可以将两个不等的对象放在一个桶中。
现在关于Comparator- 当您引入自己的类型而不是使用内置类型时,更容易理解它的逻辑。
例如,让我们说我们有一流的Apple具有两个属性:weight和price,并希望把out对象这种类型的进入有序集合TreeSet。
public class Apple {
private int weight;
private int cost;
Run Code Online (Sandbox Code Playgroud)
现在,您希望如何在集合中对这些苹果进行排序 - 您是要按weight还是按对它们进行排序price?编译器将如何决定?
提供适当的Comparator或Comparable允许您传递您的意图。让我们尝试将对象添加到集合中。
public class Apple {
private int weight;
private int cost;
public static void main(String[] args) {
Apple redApple = new Apple();
redApple.setCost(10);
redApple.setWeight(2);
Apple greenApple = new Apple();
greenApple.setCost(12);
greenApple.setWeight(3);
Set<Apple> apples = new TreeSet<>();
apples.add(redApple);
apples.add(greenApple);
System.out.println(apples);
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
@Override
public String toString() {
return "Apple [weight=" + weight + ", cost=" + cost + "]";
}
}
Run Code Online (Sandbox Code Playgroud)
如果你运行上面的代码,你会得到 RuntimeError : Apple cannot be cast to java.lang.Comparable,因为编译器必须弄清楚你想如何比较你的苹果。所以让我们修复它:让我们实现Comparable接口
public class Apple implements Comparable<Apple> {
Run Code Online (Sandbox Code Playgroud)
和覆盖compareTo方法
@Override
public int compareTo(Object obj) {
int cost = ((Apple) obj).getCost();
return this.getCost() - cost; // sorting in ascending order.
// change to this to sort in Descending order
// return cost - this.getCost();
}
Run Code Online (Sandbox Code Playgroud)
现在有了这些更改,让我们运行我们的代码:
[Apple [weight=2, cost=10], Apple [weight=3, cost=12]]
Run Code Online (Sandbox Code Playgroud)
我们的收藏按成本升序排列。
现在,如果您无权访问Apple类并且无法更改源代码以实现Comparable.
这是有Comparator帮助的地方。
删除implements Comparable,因为我们假设我们不能修改这个类
public class Apple {
Run Code Online (Sandbox Code Playgroud)
和删除方法
@Override
public String toString() {
return "Apple [weight=" + weight + ", cost=" + cost + "]";
}
Run Code Online (Sandbox Code Playgroud)
添加比较器实现:
public class AppleComparator implements Comparator<Apple> {
@Override
public int compare(Apple app1, Apple app2) {
return app1.getCost() - app2.getCost();
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以只提供Comparator给收藏来表达我的意图
Set<Apple> apples = new TreeSet<>(new AppleComparator());
Run Code Online (Sandbox Code Playgroud)
集合将再次按成本排序,对应于提供的比较器。因此,我们需要提供Comparator或Comparable以便将它们存储在集合中,特别是在TreeSet.
现在关于您的问题:Comparator和equals()method之间没有联系。Comparable(compareTo() method ) 和equals()method之间只需要一致性。
示例 - 在上面提到的Apple类中,在实现 Comparable 的版本中,我们引入了用于确定相等性的新逻辑。compareTo()如果两个对象相等,则该方法返回 0,而如果两个对象相等,则您的equals()方法返回 true。
compareTo()当 x.compareTo(y) 等于 0 时,使用required 与 equals 一致的自然顺序为真。 所以你必须使你的Comparable类与 equals 一致,因为如果compareTo()和equals()方法没有返回一致的结果。
以下示例显示了与 equals 不一致的 compareTo() 方法:
public class Apple implements Comparable<Apple> {
private int weight;
private int cost;
private String color;
public boolean equals(Object obj) {
if(!(obj instanceof Apple)) {
return false;
}
Apple other = (Apple) obj;
return this.weight == other.weight;
}
public int compareTo(Apple obj) {
return this.cost.compareTo(obj.cost); }
}
Run Code Online (Sandbox Code Playgroud)
如果我们想按成本对 Apple 对象进行排序,但成本可能不是唯一的。可能有两个具有相同成本的对象。因此,compareTo()比较两个相等的Apple对象时, 的返回值可能不为0 ,这意味着该compareTo()方法与 不一致equals()。
您覆盖的方法equals()位于 中,MyComparator class因此如果您需要比较 2 个实例,则会使用该方法Mycomparator;)
这不是你正在做的,你正在比较int,所以是的,该compare()方法很有用,因为它将用于sorting但Treeset这里不会使用 equals 方法
在 99% 的情况下,您不需要override equals在类中使用方法implements Comparator,因为它们在这里只是为了将compare自己的值而不是另一个值,事实上,因为大多数时候它们必须具有属性,所以您不会有 comparatorequals 。
| 归档时间: |
|
| 查看次数: |
7167 次 |
| 最近记录: |