简体   繁体   English

我们可以动态更改equals方法的行为吗?

[英]Can we change behavior of equals method dynamically?

I have one class having two variables named as x and y . 我有一类有两个名为xy变量。 In this class I have overrided the equals and hashCode methods to compare two object of this class. 在此类中,我重写了equalshashCode方法来比较此类的两个对象。 But our requirement is to compare two object of this class sometimes on the basis of x and sometimes on the basis of y . 但是我们的要求是有时基于x有时基于y比较此类的两个对象。 Is it possible dynamically in Java? 用Java动态地可以吗?

Edit: I have one more class named as B, in this class there is two method m1 and m2 and I want to compare the above class object in such a way that when we call from m1 (for sorting) the above objects will be compared on the basis of x (means compare object by compare x variable) and when we call from m2 (for sorting) then we compare according to y. 编辑:我还有一个名为B的类,在这个类中有两个方法m1和m2,我想比较上面的类对象,当我们从m1调用(进行排序)时,将比较上面的对象基于x(通过比较x变量表示比较对象),当我们从m2调用(进行排序)时,我们根据y进行比较。

Changing behavior based on last method to call your method is possible, but you shouldn't do it for a lot of reasons. 可以基于最后一个方法更改行为以调用您的方法,但是出于很多原因,您不应该这样做。

  • it violates the equals contract, thus breaking the functionality of several algorithms designed to handle collections 它违反了等价合约,因此破坏了旨在处理集合的几种算法的功能
  • result of the comparison cannot be anymore known without knowing the caller, which is a hard dependency that's prone to break 不知道调用者就无法知道比较的结果,这是一个容易打破的硬依赖关系

However, if you insist you need it, you can do like 但是,如果您坚持需要,那么您可以喜欢

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
if (stackTraceElements.length < 3)
{
    // do something when last method to call is not available
    // probably you'll want to return something
}
String callerMethod = stackTraceElements[2].getMethodName();
if (callerMethod.equals("m1"))
{
    // something
} else
{
    // something else
}

This example is simplified as it assumes the method calling this method is the candidate - it can be some method further down the call stack. 此示例得到了简化,因为它假定调用此方法的方法是候选方法-它可以是调用堆栈之后的某些方法。

As noted, this is not recommended. 如前所述,不建议这样做。 Rather use different kind of comparators for the purpose, and give a relevant comparator to the sort method to have different kind of sorting per context. 而是为此目的使用不同种类的比较器,并为排序方法提供相关的比较器,以使每个上下文具有不同种类的排序。

Depending on the complexity of the comparison, you can either do this within the class or use two seperate comparator classes. 根据比较的复杂程度,您可以在该类中执行此操作,也可以使用两个单独的比较器类。

public boolean equals(Object other){
    if(condition == true){
        return x==x;
    }else{
        return y==y;
    }
}

or 要么

public boolean equals(Object other){
    if(condition == true){
        return new CompareX(this, other).compare();
    }else{
        return new CompareY(this, other).compare();
    }
}

You have to extend the comparison logic to a valid one, of course. 当然,您必须将比较逻辑扩展到有效的逻辑。

Oh and, the same principle applies to the hashCode. 哦,同样的原理适用于hashCode。

It's not possible, to change the behaviour of equals dynamically. 动态更改equals的行为是不可能的。 You have to use Comparator to provide the comparison from the outside of the class. 您必须使用Comparator从类外部提供比较。

Since Java8 with Lambdas it is easy to use Comparators . 由于Java8与Lambdas一起使用,因此Comparators器易于使用。

There is a method comparing . 有一种comparing方法。 You can create Comparators out of Methods, which you want to compare. 您可以在要比较的方法中创建比较器。

// A comparator comparing on x
Comparator<A> comp1 = comparing (a -> a.x); 
// A comparator comparing on the output of m1
Comparator<A> comp2 = comparing (A::m1);
// A comparator comparing on the output of m1 and when equals, comparing on x
Comparator<A> comp2 = comparing (A::m1).thenComparing (a -> a.x);

From the external point you can decide, which comparator to use. 从外部可以确定使用哪个比较器。

There's a new way to sort your data in Java8, too: 还有一种在Java8中对数据进行排序的新方法:

List<A> data;
data.stream ().sorted (comparing (a -> a.x));

Of course you have to be allowed to use Java8 for this. 当然,必须允许您为此使用Java8。

If you can add flag setting code to m1 and m2 you can modify eis answer to get rid of the kludgy stacktrace stuff. 如果可以将标记设置代码添加到m1和m2,则可以修改eis答案以摆脱kludgy stacktrace的内容。

It is still kludgy. 它仍然很混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM