equals() method of java - java

I've the following test program. I create 3 Integer references. I create 2 Integer objects and make references i1 and i2 refer them respectively. I make reference i3 equal to i1. Now i1 equals() i3 should be obviously true as they both refer to same object on heap. But why should i1 be equal() to i2 ? They are refering to two different objects. What am I missing.
The documentation says:
public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
public class Test{
public static void main(String [] args)
{
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
Integer i3 = i1;
if(i1.equals(i3)) // UNDERSTANDABLE
System.out.println("equal");
if(i1.equals(i2)) // prints equal. WHY !!!!!
System.out.println("equal");
}
}

The equals() methods for the wrapper types test for value equality, if you want to test reference equality, use == instead, e.g.
System.out.println(new Integer(1) == new Integer(1));

equals is the value version of equality. Classes override this method to define what value equality means. For example, to see if two strings contain the same sequence of characters, you use the .equals() method. If creating your own class, and, for example, you want to add it to a HashMap, you would have to define both a hashCode() and an equals() method for it to work properly.
To see if two references point to the same memory location, use ==.

Because i1 and i2 have the same value. Integer.equals() is implemented like this:
public boolean equals(Object obj) {
return (obj instanceof Integer
&& intValue() == ((Integer) obj).intValue());
}
So i1 and i2 are Integers and they have the same value, so it will return true.

The equals method of the Integer class compares the int values that Integer wraps. As 10 is equal to 10, i1 and i2 are considered equal.

By looking at the Integer class you may get a better idea why. Here is the code is below
/**
* Compares this object to the specified object. The result is
* <code>true</code> if and only if the argument is not
* <code>null</code> and is an <code>Integer</code> object that
* contains the same <code>int</code> value as this object.
*
* #param obj the object to compare with.
* #return <code>true</code> if the objects are the same;
* <code>false</code> otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;

This is the implementation of equals() in Integer:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
with that in mind, if the value of i1 is 10, and the value of i2 is also 10, then 10 == 10 would return true.

If you read further in the JavaDoc, it provides more details, specifically:
Indicates whether some other object is
"equal to" this one. The equals
method implements an equivalence
relation on non-null object
references:
It is reflexive: for any non-null reference value x, x.equals(x) should
return true.
It is symmetric: for any non-null reference values x and y, x.equals(y)
should return true if and only if
y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if
x.equals(y) returns true and
y.equals(z) returns true, then
x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple
invocations of x.equals(y)
consistently return true or
consistently return false, provided no
information used in equals comparisons
on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
Specifically, it is up to the implementor of "equals(Object)" to decide if two objects are "equal." For reference comparison, us the == operator as others have pointed out.
I also encourage you to read Effective Java if you're interested in this (and other similar) topics.

The answer to your question has been already said but I have one note. Be careful because your own objects are extended from Object and there is method equal() implemented like operator == so if you want to compare values you have to override it.

Also note that "Using new Integer(int) is guaranteed to always result in a new object, whereas Integer.valueOf(int) allows caching of values to be done by the compiler, class library, or JVM. Using of cached values avoids object allocation and the code will be faster." --FindBugs
Compare these statements:
System.out.println("new == " + (new Integer(1) == new Integer(1)));
System.out.println("new equals() " + new Integer(1).equals(new Integer(1)));
System.out.println("valueOf() == "
+ (Integer.valueOf(1) == Integer.valueOf(1)));
System.out.println("valueOf() equals() "
+ Integer.valueOf(1).equals(Integer.valueOf(1)));
which produce this output:
new == false
new equals() true
valueOf() == true
valueOf() equals() true

They have same value, that's why it is true. Generally equals method does not test if the references are equal although that is the default behavior.

Related

ArrayList's contains() method always returns false with custom object

I'm having some troubles with getting on with my code, I'll give you an simple example (though it's going to be a little more complex, this simple code doesn't work properly either).
class Sign {
private String char;
private Integer freq;
public Sign(String c) {
this.char = c;
}
#Override
public boolean equals(Object o) {
String check = (String)o;
return check.equals(this.char);
}
#Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.char.hashCode();
return hash;
}
}
I assume that there's always will be a String in equals method for simplicity reasons. There's some hashCode() also to make sure that the contains() method will work and here's the test itself:
ArrayList<Sign> queueOfSigns = new ArrayList<>();
Sign test = new Sign("C");
String c = "C";
queueOfSigns.add(test);
if(queueOfSigns.contains("C"))
System.out.println("I am here!");
No matter what, this simple test-code always returns false in that case - so "I'm here" message never appears. I've been trying some different ways of approach my code but it was because the idea of this is to get single characters from String text and check whether the single character is already present in the ArrayList. Nevertheless - without getting this simple test working properly I can't move on, so I would like to ask you - what am I missing. It's my first time actually with using equals() and hashCode() methods to get my own object working properly with contains() method.
Your equals implementation is incorrect. equals has a specific contract; that code attempts to violate that contract. From the documentation:
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
There's no way to make an instance of your Sign class equals to a string.
Your equals method is implemented incorrectly. It violates the general contract of Object.equals:
It is not reflexive - since it throws an exception when the argument is not a string, x.equals(x) where x is a Sign will crash with an exception.
It is not symmetric - x.equals(y) does not return the same value as y.equals(x), if y is a string and x is a Sign
It is not consistent - since it can possibly throw exceptions when the argument is not a string, not just return true or false.
On a low level of abstraction, the cause of this problem is the implementation of contains. As per the docs:
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).
ArrayList actually calls o.equals(e) with o being the string you passed in. So it actually calls the equals method in String.
If contains called e.equals(o), then your program would have printed "I'm here", but your equals still violates the contract.
A better equals implementation is something like this:
#Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o.getClass() == this.getClass()) {
Sign other = (Sign)o;
return other.$char.equals($char); // I have renamed 'char' to '$char' since the former is not a valid identifier
} else {
return false;
}
}
And your client code:
ArrayList<Sign> queueOfSigns = new ArrayList<>();
Sign test = new Sign("C");
Sign c = new Sign("C");
queueOfSigns.add(test);
if(queueOfSigns.contains(c))
System.out.println("I am here!");
EDIT:
I think this is what you are looking for:
arrayList.stream()
.filter(x -> x.getChar().equals("C"))
.findFirst().isPresent() // this returns true if a sign with C is found in the array list

How to check if two arraylist are the same (Unit test with JUnit)

Before you mark my question as duplicate, i have tried solutions in other post but didnt work. This what i have
Clientes Cliente1 = new Clientes(1,PinturasCliente1,ColoresCliente1);
Clientes Cli= new Clientes(1,PinturasCliente1,ColoresCliente1);
ArrayList<Clientes> ListaClientes = new ArrayList<Clientes>();
ArrayList<Clientes> ClientesMetodo = new ArrayList<Clientes>();
ListaClientes.add(Cliente1);
ClientesMetodo.add(Cli);
Assert.assertEquals(ListaClientes, ClientesMetodo);
This return error, and by the way PinturasCliente1 and ColoresCliente1 are ArrayList too.
So, how can I test both ListaClientes and ClientesMetodo have not the same Objects, but the Objectes they have added, have the same information.
You should overwrite the equals method on the classes of the objects you are adding to your list.
from the javadoc:
public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null
object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns
true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then
x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or
consistently return false, provided no information used in equals
comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
Parameters:
obj - the reference object with which to compare. Returns:
true if this object is the same as the obj argument; false otherwise.
note: If you override the equals method in a given class its also recommended to overwrite the hashCode method.
AbstractList.equals() is defined:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
so it use o1.equals(o2) to compare each element. In your case, it's Clientes. But Clientes.equals() by default is Object.equals(), it's defined:
public boolean equals(Object obj) {
return (this == obj);
}
Apparently, Cliente1 != Cli.
So you should override Object.equlas() in Clientes. You can check this by add
public boolean equals(Object o) { return true; }
in Clientes. Then focus on the implementation. And for PinturasCliente1 and ColoresCliente1, you'd better also implement own equals() for each of the class in case of they are not the same object.
You can override your equals method that's all objects gets from Object,
If you using maven / gradle you can import Lombok project
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven</artifactId>
<version>1.16.20.0</version>
<type>pom</type>
</dependency>
And use it to generate equals and hashcode methods auto.
#EqualsAndHashCode
public class Clientes {
}
If you implement equals() and hashCode() methods and use the equals() methods from AbstractList your program will work if only both lists contains the same elements in the same order.
If both lists contain the same elements but in different order, then it would return false even if the two lists are same in content. I do not know whether it is your requirement, but if that is, then you'll need to write your own logic to compare the lists.

Java: values are the same but if statement to check if they're equal won't work? [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Compare two objects with .equals() and == operator
(16 answers)
Closed 7 years ago.
i'm trying to see if two Song() objects are the same to eventually throw a duplicate song entry Exception but i've encountered some troubles. The if statement to check if they're equal just does not want to accept them as equal. I made the console print their values on each song entry as a test and they were printing as the same but the if statement was not initializing.
Here is my code:
case 1: //ENTER A SONG TO DATABASE
try {
Song newSong = enterSong();
int logSize = database.getLogicalSize();
if (logSize>0){
System.out.println(newSong.getName() + " " + database.getSongName(0));
if (newSong == database.getSong(0)){
throw new Exception("Exception: duplicate song entry!");
}
}
database.addSong(newSong);
}
catch (Exception e){
System.out.println(e.getMessage());
}
break;
if (newSong.equals(database.getSong(0))){
throw new Exception("Exception: duplicate song entry!");
From Oracle Doc:
"public boolean equals(Object obj)
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise."
== works for primitive types, like int , long , ... if you want to compare objects of non primitive type you have to override equals method. equal could be override like this:
#Override
public boolean equals(Object sng) {
if (!(sng instanceof Song))
return false;
if (sng == this)
return true;
Song otherSong = (Song) sng ;
//check your equality between this two here.
}
and you could use it in your function like this:
if(song1.equals(song2)){ .... }

creating a polymorphic equals expression

my question concerns altering an expression in java to make it polymorphic. The class is called csHash and is used to create hash-tables from a given datatype DT, and a given keytype KT. now, in several methods within the class (delete, search, insert, etc.) the method uses an equals function that, in the non-polymorphic version, simply uses String ( as the key in the non-polymorphic version is of the type String). what i was thinking is to create an equals method written as something along the lines of the following code. my question is... is it a valid means of testing equality?
public boolean equals(Object x) {
String i;
i = new String[1];
String y;
y = new String[1];
i == i + this; // use the + operator to add 'this' object
y == y + (findkey(other))x; // do the same for other object. findkey methods returns KT for a given object, i use this return to typecast the Object x.
int j = i.compareTo(y); // use built in String compare method
if(j = 0) {return true;} // use if else to determine if they are equal
else {return false;}
}
I would start by reading the spec:
Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null
object references:
It is reflexive: for any non-null reference value x, x.equals(x)
should return true. It is symmetric: for any non-null reference values
x and y, x.equals(y) should return true if and only if y.equals(x)
returns true. It is transitive: for any non-null reference values x,
y, and z, if x.equals(y) returns true and y.equals(z) returns true,
then x.equals(z) should return true. It is consistent: for any
non-null reference values x and y, multiple invocations of x.equals(y)
consistently return true or consistently return false, provided no
information used in equals comparisons on the objects is modified. For
any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
In other words, as long as given three objects x, y, and z the following will hold:
x.equals(y) implies y.equals(x)
!x.equals(y) implies !y.equals(x)
x == y implies x.equals(y)
x.equals(y) && y.equals(z) implies x.equals(z)
If your equals method follows this contract, then it is a valid Java Object.equals implementation. You can create lots and lots of unit tests for this quite easily to ensure all corner cases are covered.
Note that you will also have to override hashCode with the related behavior.
Your equals method is problematic as it doesn't compare the two hash tables with all items in the buckets. Also it doesn't exclude some cases. An example override of equals method in your CSHash class looks like the following to satisfy the general guideline of equals method:
#Override
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof CSHash))
return false;
CSHash other = (CSHash) o;
return this.entrySet().equals(other.entrySet());
}
Here it assumes that you have defined entrySet() method in your CSHash class to return the set of your hash table. You can define your own entrySet() method similar to the one in Java's HashMap class.

Integer equals method

Normally when you have an object an objects Equals methods is equal to another object of same type if the two hashcodes are alike.
Does Integer work the same way by comparing hashcodes or does it work in a different way?
Two objects that have the same hashcode need not be equals().
Two objects that are equals() must have the same hashcode.
This basically means you may have (occasional) hashcode collisions.
The Integer equals() method simply compares the int value it wraps with the other Integer's int value. Hashcodes don't come into it.
Note that the equals() and hashcode aggrement is not strictly required, but it is relied upon by the numerous JDK classes that use an internal Hashtable, eg the various java.util.Hashxxx classes.
If you check the source of the Integer.java wrapper class, you can find that the equals method has been overridden to check that both the Integer objects have same int value.
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
So you can say JDK compares the integer values inside the object.
Integer equals() method compares int values as == operator does, See below code of Integer.equals() method.
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
Why is it important to you?
Integer#equals checks if two int values are equal, and not just references. So the actual Integer objects might be different (different references), however be equivalent.

Categories