当前位置: 首页 > 知识库问答 >
问题:

比较器:等于方法函数

酆景辉
2023-03-14

实际上,我正在通过其中一个教程,其中提到,当我们需要实现比较器接口时,我们可以覆盖equals方法(但是没有必要覆盖)。

所以,只是为了更好地理解

我重写了下面的方法

测验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);
    }
}

MyComparator.java

导入java。util。比较器;

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;
    }
}

对于其他场景

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;
    }
}

现在不管我从equals方法返回什么,不管是真是假。。它返回相同的树集值。如果有人能澄清equals方法的函数性的概念,请

共有3个答案

阳勇
2023-03-14

您覆盖的equals()方法位于MyComparator类中,因此如果需要比较MyComparator的两个实例,将使用该方法

这不是你正在做的,你正在比较int,所以是的,比较()方法是有用的,因为它将用于排序Treeset,但是这里的equals方法不会被使用

在99%的时间里,你不需要在实现的类中重写equals方法,因为它们在这里只是为了比较值而不是它们自己,事实上是因为大多数时候,它们必须具有属性,你不会有比较器等于。

裴彦
2023-03-14

类的equals()方法,比较器比较器需要相等的一致性,因为如果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

正如你所看到的,我们有不同的行为。为什么呢?这是因为String类实现了一个equals()方法,该方法检查值是否相同。另一方面,StringBuilder不实现equals()方法,而是使用Objectclass提供的equals()实现。而Object类提供(继承)的实现只会简单地检查两个引用的对象是否相同。

因此,为了检查两个对象是否相等,Java使用equals()方法,并且每当引入自己的类型时,如果不想依赖equals()方法的Object类实现,则必须重写equals()方法

例如,让我们介绍我们自己的类型:简单类苹果

public class Apple  {

    private int weight;
    private int cost;
    private String color;

现在你怎么决定两个苹果是否相等?按颜色、重量、价格还是别的?这就是为什么您需要显式地提供自己的equals方法,以便可以比较您类型的对象是否相等。

下面的示例比较了两个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;
    }

您可以为equals()方法实现任何您喜欢的逻辑。Javaequals()方法非常重要,它提供了开发者应该遵循的契约或重要规则。我不会列出它们,你从这里得到它们,它们是合乎逻辑的,非常直截了当。

还有另一个合同equals()-每当您重写equals()时,您也需要重写hashCode()方法。这背后的原因是,当对象作为键存储在映射中时,一些Java集合在内部使用哈希代码。

Hashcode是将对象分类为多个类别的数字。想象一下,有人给你各种各样的苹果(红、绿、黄),当你要特定种类的苹果时,你被要求把它们还给你。如果您对它们进行分类,将它们分别放在不同的桶中,并在任何时候要求进行特定排序(为简单起见,让我们说“红苹果”)时,都会更加高效和快速,而且您已经对它们进行了分类,您可以更快地检索它们。希望现在清楚了为什么需要实现hashcode()hashcode()equals()方法有自己的约定或规则。它们基本上是常识:

首先,同一程序内的hashcode()结果不得改变。这意味着在您的hascode()计算中,您不应该包含在程序执行过程中更改的变量。例如,若苹果的成本是可变的,也就是说,它可能会改变,那个么将它们包括在hashcode()计算中并不是一个好主意,否则结果会不一致。

第二条规则是,当使用两个对象调用时,如果equals()返回true,那么对每个对象调用hashCode()必须检索相同的结果。但是,如果使用两个对象调用equals()时返回false,则对每个对象调用hashCode()不必返回不同的结果。令人困惑为什么?因为当调用不相等的对象时,hashCode()结果不要求是唯一的-您可以将两个不相等的对象放在一个bucket中。

现在关于比较器——当您引入自己的类型而不是使用内置类型时,更容易理解它的逻辑。

例如,假设我们有一个classApple,它有两个属性:weightprice,并希望将此类型的对象放入排序集合TreeSet

public class Apple  {

    private int weight;
    private int cost;

现在你希望这个苹果在集合中如何排序——你想按重量还是按价格排序?编译器如何决定?

提供适当的比较器可比允许您传递您的意图。让我们尝试将对象添加到集合中。

  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 + "]";
    }
}

如果您运行上述代码,您将得到RuntimeError:Apple无法转换为java。lang.Comparable,因为编译器必须找到一种方法来计算您想要如何比较您的苹果。所以,让我们修复它:让我们实现Comparable接口

  public class Apple implements Comparable<Apple> {

并覆盖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();
    }

现在有了这些变化,让我们运行我们的代码:

[Apple [weight=2, cost=10], Apple [weight=3, cost=12]]

我们的收藏品是按成本升序排列的。

现在,如果您无法访问Apple类,并且无法将源代码更改为实现可比代码,该怎么办?

这就是比较器的帮助所在。

Remove实现了可比较的,因为我们假设无法修改此类

public class Apple {

和删除方法

@Override
public String toString() {
    return "Apple [weight=" + weight + ", cost=" + cost + "]";
}

添加比较器实现:

  public class AppleComparator implements Comparator<Apple> {

        @Override
        public int compare(Apple app1, Apple app2) {
            return app1.getCost() - app2.getCost();
        }

}

现在,我可以向集合提供比较器,以表达我的意图

Set<Apple> apples = new TreeSet<>(new AppleComparator());

再次收集将按成本排序,相应地提供给比较器。因此,我们需要提供比较器可比,以便将它们存储在集合中,特别是在TreeSet中。

现在关于你的问题:Comparatorequals()方法之间没有联系。只有Comparable(compareTo()方法)和equals()方法之间需要一致性。

示例-在上面提到的Apple类中,在实现Comparable的版本中,我们引入了用于确定相等性的新逻辑。如果两个对象相等,则compareTo()方法返回0;如果两个对象相等,则equals()方法返回true。

当x.compareTo(y)等于0时,使用要求与equals iff x.equals(y)一致的compareTo()的自然排序为真。因此,您必须使Comparable类与equals一致,因为如果compareTo()equals()方法没有返回一致的结果,某些Java集合类的行为可能会不可预测。

以下示例显示了与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); }
 }

如果我们想按成本对Apple对象进行排序,但成本可能不是唯一的。可能有两件物品具有相同的成本。因此,当比较两个相等的Apple对象时,compareTo()的返回值可能不是0,这意味着此compareTo()方法与equals()不一致。

明越
2023-03-14

在比较器上实现equals()方法允许您指示一个比较器提供与另一个比较器相同的排序。它与元素的排序方式无关。这是一个非常先进和极少需要的功能。您极不可能遇到实际调用比较器的equals()方法的情况。我建议你忽略它。

 类似资料:
  • 问题内容: 如果我正在从文本中扫描 //我想将行中的下一个char与 // 像这样: 我知道那不存在,但是在这种情况下可以使用任何类似的东西吗? 问题答案: 您的代码将类似于… 请注意,在调用之后,实际上已获取了该值,因此,如果您想进一步使用它,最好保留该变量,例如:

  • 问题内容: 我试图通过将结果对象与原始对象进行比较来验证例程的序列化和反序列化。这些例程可以序列化任意的和深层嵌套的类,因此,我需要一个比较例程,该例程可以提供原始实例和最终实例,并反射性地遍历每种值类型并比较这些值,然后迭代地浸入引用类型以比较值。 我已经尝试过Apache Commons Lang,但这似乎并没有进行很深入的比较,它只是比较引用类型是否相等,而没有深入研究它们: 以下代码说明了

  • 嗨,我是贾维斯的新手。 我有一个实体,我正在为它实现一个自定义比较器,以便使用Javers进行比较。 我的实体:- 包装com.devyansh.entity; 进口java.util.清单; 导入组织。贾维斯。果心元模型。注释。实体 下面我注册了新的比较器:- 我的比较器实现:- 问题领域:- 每当我尝试使用以下行进行比较时:- Diff Diff=标枪。比较(new Ent(“aaa”,new

  • 我正在做一个关于java类的介绍的作业,该作业要求使用方法将温度从摄氏转换为华氏,反之亦然。它需要使用三种比较方法,而我无法弄清楚该把什么放进去。以下是说明: 三种比较方法: -此方法将另一个温度作为参数,如果调用对象具有与other相同的温度,则返回true,否则返回false。注意,摄氏温度可以等于华氏温度,如上式所示。 -如果调用对象的温度低于其他温度,则此方法将返回true,否则返回fal

  • 我有一个客户对象类,它有一些变量,并且已经实现了一个关于其中一个变量的比较器。然而,我需要为不同的变量last_name实现另一个比较器。 因为我的Customer类中不能有2个compareTo()方法,所以我决定在这里专门创建一个Comparing类 但一旦触及Collections.sort(客户); 它不会激活下面的公共int比较(Customer Customer_1,Customerc