Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding Object#equals(Object) outside the class

Tags:

java

equals

Is it possible to override Object#equals(Object) locally when using list.contains(someObject)?

Example:

class SomeObject {
    ...
    private int id;
    private String name;

    @Overrdide
    public boolean equals(Object other){
         ...
         return this.id == other.id;
    }
}

But what if I want another kind of equals when I use list.contains(someObject)? For example I want to know if a list contains a certain name? Is it possible to override Object#equals(Object) 'anonymously'?

More specific explanation why I would need it:

int objectId = ... // Some event which passes me the attribute of an object but not the object itself

Now I have List<SomeObject> someObjects and I would like to know if this list contains an object with objectId without necessarily iterating over it.

One "solution" I could think of would be using Map<Integer, SomeObject> mapping and then someObject = mapping.get(objectId)

EDIT: My question is not a duplicate since I am specifically asking to override Object#equals(Object).

like image 372
SklogW Avatar asked Mar 24 '16 12:03

SklogW


People also ask

What is overriding with example?

Method Overriding Example We have two classes: A child class Boy and a parent class Human. The Boy class extends Human class. Both the classes have a common method void eat() . Boy class is giving its own implementation to the eat() method or in other words it is overriding the eat() method.

Can we override object?

Object , hereafter referred to simply as Object , as a base class. Because of this, all Java classes inherit methods from Object . Half of these methods are final and cannot be overridden. However, the other methods in Object can be and are overridden, often incorrectly.

What does overriding mean in Java?

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method that it overrides.


2 Answers

You can apply a filter on a stream object obtained from the list. The filter takes a predicate where you can set the condition. Then you can check if the filtered stream is not empty:

list.stream().filter(e -> e.name.equals(otherName)).findAny().isPresent()

You can make it reusable as follows for example:

private <T> boolean containsWithPredicate(List<T> list, Predicate<T> predicate) {
    return list.stream().filter(predicate).findAny().isPresent();
}

and call it as follows:

boolean containsElement = containsWithPredicate(myListOfObjects,
                                                 (e -> e.name.equals(otherName)));

EDIT:

There is a much simpler way of doing the exact same above by just calling Stream.anyMatch instead of doing filter then findAny:

list.stream().anyMatch(predicate);
like image 171
M A Avatar answered Sep 25 '22 00:09

M A


You can use a TreeSet with a custom Comparator to achieve what you want. It doesn't use equals() for equality, but rather considers that if compare() returns 0, objects are equal.

Let's say we want all Strings to be equal if they are the same length:

TreeSet<String> set = new TreeSet(new Comparator<>() {
    public int compare(String o1, String o2) {
       return o1.length() - o2.length();
    }
}
set.add("asd");
set.contains("foo");    // Returns true

This can be a useful construct (works with TreeMap as well) in cases where you need to have different "equality definitions" for objects at different times, while still working with collections.

like image 29
Kayaman Avatar answered Sep 23 '22 00:09

Kayaman