1

Suppose I have two objects and I want to know if a specific property is equal (nulls are managed exactly as I want):

// pre java 8

public static boolean equalsProp(SomeObject a, SomeObject b)
{
    Object aProp = a != null ? a.getProp() : null;
    Object bProp = b != null ? b.getProp() : null;

    return  (aProp == bProp) || (aProp != null && aProp.equals(bProp));
}

now that I have java 8, I can rewrite it to be generic:

public static <T, U> boolean equals(T a, T b, Function<? super T, ? extends U> mapper)
{
    Object aProp = Optional.ofNullable(a).map(mapper).orElse(null);
    Object bProp = Optional.ofNullable(b).map(mapper).orElse(null);

    return (aProp == bProp) || (aProp != null && aProp.equals(bProp));
}

But I don't like to define a method like this in one of my classes.

Is there a java.lang.something.SomeJreBundledClass.equals(a, b, func) that does exactly this?

Is there a best practice on how to do this (possibly without an utility method)?


Maybe it's not clear what I'm asking, I'll try again.

I have this piece of code:

Table t1 = ...
Table t2 = ...

if(!my.package.utils.ObjectUtils.equals(t1, t2, Table::getPrimaryKey))
{
    // ok, these tables have different primary keys
}

I'm asking if:

  • There's a JRE class that does the work of my.package.utils.ObjectUtils
  • There's a better, short and null-tolerant way to compare t1.primaryKey and t2.primaryKey without writing an utility method.
Cœur
  • 37,241
  • 25
  • 195
  • 267
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73
  • 1
    I highly doubt that there exists a method that does so. Checking whether certain attributes in 2 objects is quite specific. On the other hand, checking whether 2 entire objects are equal is a more sensible proposition and can be done using an inbuilt method – gabbar0x Dec 10 '15 at 14:51
  • I understand what you say; but I think it's a very common situation, and it's odd there's nothing bundled to do this kind of comparison in a short way. – Michele Mariotti Dec 10 '15 at 15:03
  • What's the harm in creating a method you just did and using it across your project? Tuples are used very commonly (and every other High level language has them in the standard library) but they aren't present int JAVA :) – gabbar0x Dec 10 '15 at 15:04
  • 1
    If you are asking for existing method which does described task then I am afraid that your question is off-topic since you are asking for existing tools recommendation. – Pshemo Dec 10 '15 at 15:09
  • @Pshemo I'm not asking for any tool recommendation... I'm asking for a **best practice**, or is this off-topic too? – Michele Mariotti Dec 10 '15 at 15:20
  • 2
    @MicheleMariotti Yes, this is off-topic as primarily opinion-based. – Tunaki Dec 10 '15 at 15:21
  • The premise that two null objects should compare equal is questionable. There is published theory that suggests "null == null" should be false. There is existing practice to back this up: for example, null in SQL; and similarly in Java Double.Nan != Double.Nan. Rather than having a method decide for you that null == null, it is safer to force the user to do it manually, thereby forcing them to think about their exact circumstance. – Klitos Kyriacou Dec 10 '15 at 15:21
  • Java is an object oriented language, watch out that you can't use it as a ore functional language. Sometimes it's better to use the "imperative" way of doing this, it's more easy and more readable. – rascio Dec 10 '15 at 15:30
  • 1
    I voted to reopen because the clarified part of the question (the edit) is explicit and neutral and doesn't ask for opinion. – Olivier Grégoire Dec 10 '15 at 15:38
  • 1
    Thanks, but I don't care about it. I needed some information, and you gave it, that's more than sufficient ;) – Michele Mariotti Dec 10 '15 at 15:40
  • 1
    Nonetheless, the question, in its second form is a good question for StackOverflow and shouldn't be closed. – Olivier Grégoire Dec 10 '15 at 15:43
  • 1
    For the record you may also compare `Optional`'s using `equals`: `Optional aProp = Optional.ofNullable(a).map(mapper); Optional bProp = Optional.ofNullable(b).map(mapper); return aProp.equals(bProp);` – Didier L Dec 10 '15 at 23:27
  • @DidierL what a coincidence: my question is "equivalent" to [yours](http://stackoverflow.com/questions/33300011/is-there-a-convenience-method-to-create-a-predicate-that-tests-if-a-field-equals) – Michele Mariotti Dec 11 '15 at 09:09
  • 1
    @MicheleMariotti yes I also noticed, a bit different though but similar. I guess we both prefer method references to "complex" lambdas and expressions ;-) – Didier L Dec 11 '15 at 09:18
  • @DidierL That's for sure :) my problem with complex lambdas is code format and readability – Michele Mariotti Dec 11 '15 at 09:23

3 Answers3

1

Consider this using streams:

static class MyClass {
    String prop;

    public String getProp(){
        return prop;
    }
}
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {

    MyClass a = new MyClass();
    MyClass b = new MyClass();
    a.prop = "foo";
    b.prop = "foo";
    boolean e = Stream.of(a,b).filter(Objects::nonNull).map(MyClass::getProp).distinct().count() != 2;
    System.out.println("e = " + e);
    a = null;
    b = null;
    e = Stream.of(a,b).filter(Objects::nonNull).map(MyClass::getProp).distinct().count() != 2;
    System.out.println("e = " + e);
}
WillShackleford
  • 6,918
  • 2
  • 17
  • 33
  • Thanks, that's what I'm talking about. But this is not so short, I wonder if there are other possibilities. – Michele Mariotti Dec 10 '15 at 15:17
  • @Tunaki, did you really read the question? I'm asking if such built-in method **does exist**, not a random built-in equals method, or if there's a way to do this **possibly without an utility method**. So the code in your comment is perfectly acceptable, but you answer wasn't. – Michele Mariotti Dec 10 '15 at 15:23
1

I'm asking if:

  • There's a JRE class that does the work of my.package.utils.ObjectUtils
  • There's a better, short and null-tolerant way to compare t1.primaryKey and t2.primaryKey without writing an utility method.

To your first question, No is the answer.

To your second question, No is also the answer, unless you're ready to have your code comparing objects quite shadily.

What you're trying to express is the equivalence. Several frameworks can help you use that context. The most notable of which is Guava with its Equivalence class/framework. In that case, you don't have to write a utility method, because they exist somewhere else.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
1

Maybe you can use something like this:

Comparator.comparing(SomeObject::getProp).compare(a, b) == 0
Comparator.comparing(Table::getPrimaryKey).compare(table1, table2) == 0
Shinigami
  • 646
  • 1
  • 7
  • 21