EDIT: the question is why cant I use ".contains" (override .equals() in the object) to compare object attributes (a string) instead of comparing the object itself.
Thanks JB:
Turns out I was confusing overriding compareTo() with overriding equals()
EDIT:
QUESTION REDEFINED:
Why cant I override equals to compare strings in my object:
public boolean equals(Object obj){
...
if(obj instanceof String){
String testString = (String) obj;
...
}
...
}
Or even overload for that matter:
public boolean equals(String stringObj){
...
}
I read somewhere that the compiler doesn't use logic to decide this, it uses types. So if I then call myObj.equals(stringOne + "_" + stringTwo) shouldn't this work as it knows a string is being passed?
Thanks,
Steve.
Why this code doesn't make sense:
because Comparable is supposed to respect rules: if a < b is true, then b > a must be true. You can compare an instance of your class with String, but a String can't compare with an instance of your custom class. You're thus breaking the contract of Comparable
because Vector doesn't use compareTo() to check if an element exists or not. It uses equals().
Because you shouldn't alter the nature of a class just to implement a specific use-case consisting in adding instances of this class to a list and check for duplicates. This logic should be outside of the class. You could simply loop through the list and check is an instance with the item and position already exists or not, before creating your custom class instance.
because you shouldn't use Vector for many years (since Java 2 - we're at Java 8). And since it seems the goal is to avoid duplicates, what you should use is a Set.
Do the right thing, and use a HashSet. Make sure CustomClass implements equals() and hashCode() correctly. You could also use a HashMap<CustomClassKey, CustomClass>, where CustomClassKey is a simple class containing the two fields identifying your CustomClass instances.
Related
I read javadoc of this JAVA API method, System.identityHashCode(Object x) and not able to understand a typical use case of this method. Classes that need hashCode() are recommended to have overridden hashCode() method of their own so what is the purpose of this method if Object class already has default hashCode()?
Suppose that class C extends class B and class B overrides hashCode and equals.
Now suppose that for class C, you wish to use the default implementation of hashCode and equals as implemented in the Object class. Normally you don't want to do that, but suppose that each instance of the C class should be a unique key in some HashMap.
You can write :
public class C extends B
{
#Override
public int hashCode ()
{
return System.identityHashCode(this);
}
#Override
public boolean equals (Object other)
{
return this == other;
}
}
Similarly, if B override's toString and you want C's toString to have the default implementation of the Object class, you can write in C :
#Override
public String toString()
{
return getClass().getName() + "#" + Integer.toHexString(System.identityHashCode(this));
}
There aren't a lot of use cases. It's primarily useful if for some reason you have a collection of objects, and only care about their object identities. This is really rare. One example is IdentityHashMap (like #Boris says). It would actually be fine to just use hashCode of the objects for such hash map, but using identity hash would theoretically be faster, because it can avoid "collisions" between objects that are logically equal but aren't the same object (it also allows avoiding of badly implemented hash functions, I guess).
There aren't a lot of use case for such collections, either. You can see use cases for IdentityHashMap here: Practical use of IdentityHashMap in Java 6
Just one difference, if the Object given is null this Method gives 0.
Example 1:
obj.hasCode();
This code throws nullPointerException if the obj is null.
Example 2:
System.identityHashCode(obj);
This method return 0 and doesn't throw an exception cause it checks for null. Also it gives the HashCode that the default hashCode method would return even if you overrides it
Did this answer help you?
I have a base class for multiple data object types in Java. I want to create an equals method in the base class, that works directly when inherited.
Equality is determined by the two objects
belonging to subclasses of the base class. This is easily achievable using
if (!(anObject instanceof BaseClass))
return false;
having the same ID. The ID field is defined by the base class so we can here test that.
if (this.id != ((BaseClass) anObject).id)
return false;
belonging to the same class. This is where I have the problem. Two objects may be of different types (and so be in different lists), but have the same ID. I have to be able to distinguish them. How can I do this?
Use
this.getClass() == anotherObject.getClass()
instead of instanceof. This will return true only if the two object belong to the same class (it's safe to check if class objects are equal by reference). And after that you may compare the id.
You should read this article for problems when implementing equals.
To make it short: use this.getClass()==other.getClass() instead of instanceof, because otherwise the equals() relationship will not be transitive (superInstance.equals(subInstance) will be true, but subInstance.equals(superInstance) will be false).
If I understand you question correctly, you need a way to differentiate two objects of same Class with same id. If so, for this you may use toString() which gives unique representation of objects unless they are string objects. Of course, you must not have overridden toString() in your base class.
example:You can use this, only for the third case that you mentioned.
if (this.toString()!= anObject.toString())
return false;
You can do that with Class.isInstance() method. In your base class, do this.
public static boolean isAnInstance(Object obj)
{
return BaseClass.class.isInstance(obj);
}
Then you can check
if (BaseClass.isAnInstance(object))
{
// Class of object is 'BaseClass' or
// it extends the 'BaseClass'
}
Hope this helps.
The best practice to know objects equality is to override hashcode() and equals() if you maitain objects in a collection
you can refer Why do we have to override the equals() method in Java?
Is it possible to compare 2 object from 2 different classes.
lets say i have an vector which adds all the objects from class A. i want to compare some string to the elements of the vector.
Example:
if(string.equals(vector.get(i)))
is this possible ?
Yes, you can call equals(). However, any reasonable implementation of SomeClass.equals() would return false if the argument is of a different class (other than perhaps a subclass).
If string is an instance of java.lang.String, this behaviour is specifically guaranteed:
The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
Your objects are at least in the class Object, and thus (at least partly) in the same class.
Equals method of an object can take any other object. However, it would be up to the implementation to not return true when comparing an apple with an orange
If the list's elements have type other than String it will always return false. From the String documentation for method equals:
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.
This is generally true for the method equals - it will or should return true only in the eventuality that the compared object is of the same class or a subclass of the former.
It's perfectly valid to write something like;
public class MyClass {
public boolean equals(Object o) {
if(o instanceof SomeUnrelatedClass) return true;
return false;
}
}
But it is not advisable, as least I would try to avoid it. It would make handling MyClass objects a little strange, for example putting them into a hash-based collection.
I have some doubts regarding equals and hashcode. What I have understood previously is, we need to override the hashcode() and equals() method in the object class if that class is supposed to add to the collection class or Map class. Please see the below example. I did not override the hashcode and equals method. Still I get the desired result what I want. One thing i understood that, If I want to compare two object we need to override the equals method. But in this example I am not comparing two objects, rather I am adding objects to collection or Map without overriding the hashcode and equals. Could anyone explain why do we need to override the hashcode and when?
package equalshashcode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EqualsAndHashCode {
public static void main(String[] args) {
Student student1 = new Student("A");
Student student2 = new Student("B");
List<Student> studentList = new ArrayList<Student>();
Map<Integer,Student> studentMap = new HashMap<Integer,Student>();
studentMap.put(1, student1);
studentMap.put(2, student2);
studentList.add(student1);
studentList.add(student2);
System.out.println("Student HashMap:: "+studentMap.get(1));
System.out.println("Before removing::"+studentList);
System.out.println(studentList.remove(student1));//true success
System.out.println("After removing::"+studentList);
}
}
class Student{
String name;
public Student(String pName){
this.name = pName ;
}
public String getName(){
return this.name ;
}
}
You don't always need to implement equals() and hashCode() to add elements into a collection.
For a List (such as you studentList, which is an ArrayList instance) it doesn't matter for most actions.
The only places where you need equals() and hashCode() is where "equality" of objects is relevant. And even in those places the default implementation might even be sufficient.
Equality matters in several cases, for example:
A Set can't contain two objects that are equal to each other
The key of a Map must have a correct equals() implementation to be retrievable (and based on the concrete Map implementation, that might imply that hashCode() has to be correctly implemented as well).
Some methods on a "normal" List also need equality. For example contains(), indexOf() and remove(Object) need correctly implemented equals()/hashCode()
Custom equals and hashCode methods are generally used for determining actual equality. If you rely on the default equals method, this will look for the same instance in memory. For example customObj1.equals(customObj2) will return false if there's no custom equals method and the two objects are separate (but otherwise equal) instances. The idea of a custom equals method is to make that same example return true if they are actually equal. A Map will then be able to use this to match the key object passed in a get(key) request to find the value without needing to have the correct instance of the key (a HashMap actually uses hashCode to do this).
The most obvious example of this being useful is for Strings, so that you can do myMap.get("key") and get the correct value, even if your key instance isn't the same as the one stored in the Map (String implements equals and hashCode for you). In general I would recommend using these Java built-in equals and hashCode methods to construct your own. For example if your object has a natural ID, such as say userName, your equals can use the String version of this to complete your own equals (you can obviously compare multiple fields):
public boolean equals(Object o) {
if (o instanceof MyObj) {
return userName.equals(((MyObj) o).userName));
}
return false;
}
As such, if you'll only be working with a single Thread, or otherwise limited variables, you'll likely never need to implement these methods, but there are certainly times when it pays off to know them.
Collection classes will work perfectly well with objects that have the default equals/hashCode implementations - there is no need to add your own for this reason.
Custom equals/hashCode methods are easy to get wrong, and unless you have a good reason to roll your own you should just stick with the ones that you get for free with java.lang.Object.
The most common reason for creating your own version of these methods is if you want to treat two separate instances of the same class as being equal. For example, if you have an Account class and you want two instances of Account which have the same accountNumber property to be regarded as equal, because they represent the same real-world account. In this case you would base your equals method on the value of accountNumber alone, and since you now have a custom equals method you need to provide a suitable implementation of hashCode as well, in order to fulfil the equals/hashCode contract.
I have to implement a one linked list but it should put object in appropriate position.
Everything was OK when I use it in conjunction with specific class, but when I tried make it universal and argument of method insert was Object some problem appeared.
When I want to input Object in right position I should use CompareTo method, but there isn't method in Object class!
The problem is how to compare two object elements without known about their real types.
Maybe I should use generic class type? But what about CompareTo? Or maybe combine with Element class and place CompareTo there?
I suppose it is feasible. :)
public void insert(Object o)
{
Element el = new Element(o);
// initializing and setting iterators
while(!it.isDone() && ((it.current().getValue())).CompareTo(o)<0)
// it.current() returns Element of List
{
//move interators
}
//...
}
You have two options:
make each object's class implement java.lang.Comparable and write the comparison logic for each class there, then just accept Comparable instead of Object and call compareTo()
create a comparator property of your list and set it on construction. The concrete comparator (implementation of java.util.Comparator) should know how to compare the objects that are put in this particular instance of your list.