if ((File_1[i].ID.equals(File_2[j].ID))
&& (File_1[i].Relation.equals(File_2[j].Relation)))
The first condition here, (File_1[i].ID.equals(File_2[j].ID) shows false when it is supposed to be true. They both have equal values.
Am I doing something wrong? This is unusual.
ID: fa001
ID: fa001
These are the values of the first 2 variables that are compared, but it shows up as false.
The original poster has said the ID is a String type and there are whitespaces around the String. In order to remove the whitespaces of String s:
s = s.trim();
However, if ID is a type you have created, make sure you implement the .hashCode() method. From the Javadocs:
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce
the same integer result.
Also make sure that .equals() is overridden from class Object to allow for your definition of whether the values of your new object type are equal.
Depending on the TYPE of ID (int, string, char[], etc) the .equals method can do some weird things. Assuming they are strings, try comparing ID.trim(), which will remove any witespace around the ID.
Related
It prints true for both of the following print statements in the sample code. I understand, its as per the logic of equals method of String class as:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
...
}
But I am unable to figure out how their hashcode remains unchanged. Does the condition, this == anObject has any relationship with the hashCode method of String class? If yes then how are they equal.
Please help me to understand this.
It is true that value of a string can be modified through reflection(where it losses its immutability nature). But in this case the hashcode remains unchanged. Why?
import java.lang.reflect.Field;
public class StringHacker {
public static void main(String[] args) throws Exception {
String myMonth = "January";
char[] yourMonth = {'M', 'a', 'y'};
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(myMonth, yourMonth);
System.out.println(myMonth.equals("January"));
System.out.println(myMonth.equals("May"));
}
}
The output is:
true
true
But in this case the hashcode remains unchanged. Why?
The answer is that String::hashCode caches its result in a private field. So if you do this:
String s = /* create string */
int hash = s.hashcode();
/* use reflection to mutate string */
int hash2 = s.hashCode();
you will find that hash and hash2 are the same value. This is just one more reason why it is a bad idea to use reflection to mutate strings.
(But if you read the code for String you can see how hashCode is implemented and then use reflection to clear the cached hashcode value.)
The hashcode does not change because String is an immutable class.
That means by contract its value will not change. As the same value must always have the same hashcode, there is no need ever to change the hashcode. Even worse, an object with a hashcode changing over time may get you in big trouble, e.g. when dealing with Set and Map.
An object must not change its hashcode!
If you alter a string's value via reflection you're actively breaking the contract and thus causing undefined, chaotic and possibly catastrophic behaviour.
You mention hashcode in your question, but never call it nor display it's value, nor compare hoshcode values. So to answer your question :
Does the condition, this == anObject has any relationship with the hashCode method of String class?
The answer is an emphatic "no" (other, of course, than the obvious case that two references to the same object will obviously be calling the same method and get returned the same result). Likewise, hashcode() is also not called/considered by the equals() method.
So let's consider ==, equals(), and hashcode(), and how these play out in your example. Firstly, though, it must be mentioned that you are using reflection in a way that it was never intended to be used. There are situations where calling value.set(object, value) is valid and necessary - but changing the value of an immutable class like "String" is not one of them. Upshot is that it's not surprising to get weird results by doing things like that.
Let's start by restating that every object (such as a String) lives at its own location in the computer's memory. For example, consider code like :
String myName = "Fred";
String yourName = "Fred";
String databaseName = fetchNameFromDatabase(); // returns "Fred"
boolean mineIsYours = (myName == yourName); // true
boolean mineIsDatabases = (myName == databaseName); // false
boolean mineEqualsDatabases = myName.equals(databaseName); // true
All 3 Strings will have the same value "Fred" - but there's a neat trick. When the Java compiler compiles the program, it will load all hard-coded strings into the .class file. Since Strings are immutable, it saves some space by creating unique values in a "String pool" - so for my example, "Fred" will only be created ONCE, and myName and yourName will both be pointing to the SAME instance in memory - hence mineIsYours will be true.
Strings created dynamically (eg read from the database) would not use this String pool, so will be different instances even though they may have the same value - hence the importance to test equality using equals() rather than ==.
Can you now see what's happening in your program ? Let's look at a few specific lines :
String myMonth = "January";
"January" is a hard-coded constant, so it's put in the String pool, and myMonth is pointing to the location of that instance in memory.
value.set(myMonth, yourMonth);
The value of myMonth - ie, the value of that instance in memory that myMonth is pointing to - is changed to be "May".
System.out.println(myMonth.equals("January"));
Calls "equals" on myMonth, passing in the instance of the hard-coded String that the Java compiler put into the String pool for "January". However, this instance is THE SAME INSTANCE that myMonth was initialised to (remember my variable mineIsYours was true) !! Yes, THE SAME INSTANCE that you changed the value of to be "May".
So, when you changed myMonth's instance value in the String pool from "January" to "May", you didn't just change it for that one myMonth variable, but for EVERY hard-coded "January" value in the program !
System.out.println(myMonth.equals("May"));
The value of the instance that myMonth is pointing to has been changed to "May", so this is true.
So where is hashcode() used in all this ? As I mentioned earlier, it isn't. Not at all.
From your question, I'm wondering : is your understanding that two objects are equal if their hashcodes match ? If so, no - not at all. There is NO - repeat NO - requirement that hashcodes be unique, which means the idea of "equal if hashcodes match" obviously fails.
The purpose of hashcode() is to give a wide spread of values for different instances of the class. This is used in structures like HashMap,etc to put objects into different "buckets" for quick retrieval.
The implicit connection between equals() and hashcode() is that :
1) where one is created (or rather, overridden), then the other
should be as well, and
2) hashcode() calculation should use the
exact same fields as equals() - no more and no less.
I am trying to use a mock and check that the argument passed into the mock is the correct ArrayList<MyModel>. I have defined the boolean equals method on MyModel, but I can't find the right matcher that uses the equals method. The matchers I have been writing only compare the object_id's which are obviously different. My test looks something like so:
MainActivity activity = mock(MainActivity.class);
MyRequest subject = new MyRequest(activity);
ArrrayList<MyModel> list = ...;
subject.makeRequest();
verify(activity).handleSuccess(argThat(is(list)));
Does anyone know a matcher that will use the boolean equal on MyModel?
According to the Hamcrest tutorial, you can use any of the following to compare using Object.equals:
argThat(is(list))
argThat(is(equalTo(list))
argThat(equalTo(list))
Furthermore, List.equals(Object) is specifically defined to compare e1.equals(e2) for every element e1 and e2 in corresponding positions in the list.
Double-check that you've fulfilled everything you need to do to properly override equals:
Does your MyModel.equals method receive an Object parameter instead of a MyModel? If the parameter is any type other than Object, it isn't a proper override and won't work.
Is MyModel.equals reflective, symmetric, transitive, and consistent? It's unlikely that your equals would fail in the other direction, but there's no guarantee on which object the equals method will be called.
When two objects are equal, do their hashCode values return equal integers? Collection implementations are free to check hash code equality as a "shortcut" before checking object-to-object equality.
To check those points, you may want to write a test to specifically for equals. I recommend Guava's EqualsTester, which checks most of these properties automatically for you.
The output of the below code is false
String str = "3456";
String str1 = "3456";
System.out.println(Integer.valueOf(str).equals(str1));
I didn't understand it. I thought it will return true. As I am preparing for SCJP, understanding the reason behind it may be helpful. Can someone please help?
An Integer will never be equal to a String.
Both classes have very strict equals() definitions that only accept objects of their respective types.
Integer.equals():
The result is true if and only if the argument is not null and is an Integer object that contains the same int value as this object.
String.equals():
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.
That's actually a quite common way to implement equals(): only objects of the same class (and occasionally subclasses) can be equal. Other implementations are possible, but are the exception.
One common exception are the collections such as List: every List implementation that follows the convention will return true when compared to any other implementation, if it has the same content in the same order.
Usually, when implementing equals(), one of the first things to do is to check whether the objects are of one and the same type.
public boolean equals(Object obj) {
if (!(obj instanceof SomeType)) return false;
...
}
This is also applied in the Integer and String classes, which answers the question why do you receive false as a result.
The general contract of the equals() methods states (among other things) that the objects that are being compared need to be of the same class. That's why you'll never be able to compare Apples with Oranges.
For the full contract of the equals() method, see the javadocs.
a Integer Object can't equals with String Object
use :
boolean a = str.equals(str1);
OR
boolean a = (Integer.parseInt(str) == Integer.parseInt(str1));
I've been working in my project (I'm also using EMF Compare). I need to keep an unique ID for each object that I'm using, that's why I decided to use the IdentityHashCode, as far as I understand, this value is the same through the compilation.
I have given the object as a parameter in the method of another class, but when I try to get the hashcode this is not the same that I can see when I print the value of the object.
Something like this:
System.out.println("The Object is: "+obj)
System.out.println("The hash ID is: +Integer.toHexString(System.identityHashCode(obj)));
But as a result I get this:
The Object is : ***xxxxxxxxxxxxxx***.EntityImpl#18e588c (name: Comment) has been removed.
The hash ID is: 1ec1758
As you can see the two values (18e588c and 1ec1758) are totally different, but I can't understand why. Until now the only thing that I have done (and it works) is to get the String of the object and then use the substring method to get 18e588c (for this example)
I'd appreciate any answer.
I need to keep an unique ID for each object that I'm using, that's why I decided to use the IdentityHashCode, as far as I understand, this value is the same through the compilation.
No. It's got nothing to do with compilation, and it's not guaranteed to be unique.
It's not clear what you're trying to do, but you simply shouldn't regard hash codes as unique - they're not guaranteed to be.
The Object.hashCode documentation specifies:
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
That's not the same thing as guaranteeing it though.
You're also being confused by the result of calling toString() - I suspect your class actually overrides hashCode(), and Object.toString() calls the potentially-overridden hashCode() method rather than using the identity hash code:
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
If you call obj.hashCode() you'll see the same value that's shown by toString.
I know that == has some issues when comparing two Strings. It seems that String.equals() is a better approach. Well, I'm doing JUnit testing and my inclination is to use assertEquals(str1, str2). Is this a reliable way to assert two Strings contain the same content? I would use assertTrue(str1.equals(str2)), but then you don't get the benefit of seeing what the expected and actual values are on failure.
On a related note, does anyone have a link to a page or thread that plainly explains the problems with str1 == str2?
You should always use .equals() when comparing Strings in Java.
JUnit calls the .equals() method to determine equality in the method assertEquals(Object o1, Object o2).
So, you are definitely safe using assertEquals(string1, string2). (Because Strings are Objects)
Here is a link to a great Stackoverflow question regarding some of the differences between == and .equals().
assertEquals uses the equals method for comparison. There is a different assert, assertSame, which uses the == operator.
To understand why == shouldn't be used with strings you need to understand what == does: it does an identity check. That is, a == b checks to see if a and b refer to the same object. It is built into the language, and its behavior cannot be changed by different classes. The equals method, on the other hand, can be overridden by classes. While its default behavior (in the Object class) is to do an identity check using the == operator, many classes, including String, override it to instead do an "equivalence" check. In the case of String, instead of checking if a and b refer to the same object, a.equals(b) checks to see if the objects they refer to are both strings that contain exactly the same characters.
Analogy time: imagine that each String object is a piece of paper with something written on it. Let's say I have two pieces of paper with "Foo" written on them, and another with "Bar" written on it. If I take the first two pieces of paper and use == to compare them it will return false because it's essentially asking "are these the same piece of paper?". It doesn't need to even look at what's written on the paper. The fact that I'm giving it two pieces of paper (rather than the same one twice) means it will return false. If I use equals, however, the equals method will read the two pieces of paper and see that they say the same thing ("Foo"), and so it'll return true.
The bit that gets confusing with Strings is that the Java has a concept of "interning" Strings, and this is (effectively) automatically performed on any string literals in your code. This means that if you have two equivalent string literals in your code (even if they're in different classes) they'll actually both refer to the same String object. This makes the == operator return true more often than one might expect.
In a nutshell - you can have two String objects that contain the same characters but are different objects (in different memory locations). The == operator checks to see that two references are pointing to the same object (memory location), but the equals() method checks if the characters are the same.
Usually you are interested in checking if two Strings contain the same characters, not whether they point to the same memory location.
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
The JUnit assertEquals(obj1, obj2) does indeed call obj1.equals(obj2).
There's also assertSame(obj1, obj2) which does obj1 == obj2 (i.e., verifies that obj1 and obj2 are referencing the same instance), which is what you're trying to avoid.
So you're fine.
Yes, it is used all the time for testing. It is very likely that the testing framework uses .equals() for comparisons such as these.
Below is a link explaining the "string equality mistake". Essentially, strings in Java are objects, and when you compare object equality, typically they are compared based on memory address, and not by content. Because of this, two strings won't occupy the same address, even if their content is identical, so they won't match correctly, even though they look the same when printed.
http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/
"The == operator checks to see if two Objects are exactly the same Object."
http://leepoint.net/notes-java/data/strings/12stringcomparison.html
String is an Object in java, so it falls into that category of comparison rules.