I was surprised to see that equals() is apparently overridden for ArrayList<String>. Because contains() in Collection<> apparently compares values, not references. Of course, for Collection<Object>, references would be compared. In the program below, shouldn't I get false on the second line?
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("Obama");
al.add("Reagan");
al.add("Bush");
al.add("Nyquist");
StringBuffer sb = new StringBuffer();
sb.append("Bush");
System.out.println("compares values? using constants " + al.contains("Bush"));
System.out.println("compares values? using local variable " + al.contains(sb.toString()));
}
run:
compares values? using constants true
compares values? using local variable true
Javdaocs for List are you friend. List.contains() relies on .equals():
boolean contains(Object o)
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)).
String.equals() compares the Strings contents (characters):
public boolean equals(Object anObject) 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 exactly the output you should expect, and Collection<Object> would be no different. All Collection types, unless specified otherwise, use .equals(Object), and differing implementations violate the Collection contract. (And to be clear, upcasting a String to an Object does not change the behavior of its equals method.)
There is some precedent -- see e.g. the TreeSet implementations, which use comparison-based equality, and IdentityHashSet, which uses reference equality -- but these should usually be used only when the two notions of equality match, or for significant and unusual need.
you can try System.out.println(sb.toString().equals("Bush")); in your class and see what it returns. It will return true. So in the second case it is returning/printing true.
Related
on the oracle java documentation,
equals() from list says two lists are defined to be equal if they contain the same elements.
But from object class equals() return true only if their hash code is equal.
It means equals() from list overrides equals method from object class. And it's same for equals() from string. As long as they have same characters, they return true.
so whenever I declare a type as String, or use list classes like arraylist
equals() are overriden automatically righT?
equals() are overridden automatically righT?
Answer : Yes absolutely right, If you are asking overriden .equals() method is invoked automatically at run time
**Object class is parent class for every class in java and it consist of .equals() method which compares the object references
But String class, Wrapper classes (Integer,Long etc..) and Collections Classes (ArrayList, hashSet etc..) are overridden .equals() method to compare content in object instead of object references
to avoid confusions here is the clear example
public class Main2 {
public static void main(String[] args) {
List<String> l1 = new ArrayList<>();
l1.add(new String("hello"));
List<String> l2 = new ArrayList<>();
l2.add(new String("hello"));
System.out.println(l1.equals(l2)); //true
List<Test> t1 = new ArrayList<>();
t1.add(new Test());
List<Test> t2 = new ArrayList<>();
t2.add(new Test());
System.out.println(t1.equals(t2)); //false
}
}
class Test{
}
In the above example comparing List<String> will return true because .euqals() method in String is overridden to compare content
But while comparing Lits<Test> will return false even though both objects are empty, since .equals() method in Test class is not overridden by default it will invoke Object class .equals() method which compares reference of objects as == does
Google Question object class equals method compares hashcode ?
Answer
The java.lang.Object class requires that any two objects that compare equal using the equals() method must produce the same integer result when the hashCode() method is invoked on the objects [API 2014]. The equals() method is used to determine logical equivalence between object instances.Feb 12, 2018
equals() are overriden automatically righT?
No. Methods are not overwritten "automatically".
You can look at the code - both classes have their own implementation of equals and hashCode. This implementation is what is used at runtime. If you're writing your own class, you will likely implement equals and hashCode.
But from object class equals() return true only if their hash code is equal.
I think you (and the original version of the other answer) are misunderstanding the documentation on equals:
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.
The only part of this that refers to hashCode is at the end, which specifies that equal objects must have equal hash codes - this isn't automatic, it's by convention so things like HashMap will work.
Comparing hashCode values is NOT the default implementation of equals, and should NEVER be the implementation of equals - it is possible to have multiple non-equal objects with the same result for hashCode. The rule is to make sure your hashCode implementation returns the same value if objects are equal.
As an example, both of these will output the same hashCode, but are clearly not equal:
System.out.println("Aa".hashCode());
System.out.println("BB".hashCode());
Recommended further reading: this related question.
No, .equals() would not magically get overwritten when String are getting compared in list.
the String Class in java already has the .equals() method overwritten in its definition to compare characters by default.
meaning, even without a list if you do this:
String a = new String("abc");
String b = new String("abc");
System.out.println(a.equals(b));
Then, your output would be true
refer this: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html
i am trying to create all subsets of a set and group them without duplicates. For example, in a set like {1,2,3,4,5,6}, {(1,2), (3,4), (5,6)} this tuple can be valid on the other hand {(1,2), (2,4), (5,6)} this tuple shouldn't be valid since it has two instance of number 2 although the set has only one instance of number 2.
To guarantee this non-duplicate form, i have a small method that checks the given subset, if it has the number that is passed to the method as parameter, it returns true.
The problem with that, when there is duplicate in the set like {1,2,3,1,5,6} it shouldn't say that the second "1" is equal to first "1". To make this happen, i used "==" operator to compare the object references and i hoped that this will make difference between first "1" and the second "1", but it didn't. Apparently, Eclipse creates same object reference for same type of objects which is created in compile-time and have same value. How can i force Eclipse to create different object references ? If there is a way to flag objects with unique number, that helps also.
Here is the method:
private boolean doesTuplesHave(Integer number, ArrayList<ArrayList<Integer>> tuples){
for(ArrayList<Integer> list : tuples){
for(Integer numinTuple : list){
if( numinTuple == number){
return true;
}
}
}
return false;
}
a) Eclipse has nothing to do with it, this is standard behavior for all Java compilers and JVMs.
b) use .equals()
if(numinTuple.equals(number))
or, if it's possible that one of the sides can be null, use Objects.equals():
if(Objects.equals(numinTuple, number))
Explanation: in Java, the == operator checks reference equality, not semantic equality (i.e. is this the same object vs do these objects have the same value)
See: What is the difference between == vs equals() in Java?
Also, in Java 8, your method can be rewritten in a more concise way as:
return tuples.stream().anyMatch(l->l.contains(number));
(which also fixes your bug)
The question is about static methods Objects.deepEquals class (since Java 7):
public static boolean deepEquals(Object a, Object b) {
if (a == b)
return true;
else if (a == null || b == null)
return false;
else
return Arrays.deepEquals0(a, b);
}
As it said in javadoc of this method:
Returns true if the arguments are deeply equal to each other and false
otherwise.
What I do not understand: where is the depth of comparison? As we can see inside its implementation it just does references comparison, and inside Arrays.deepEquals0(a, b) for simple Object and Object arguments it invokes
just: eq = e1.equals(e2);. So in what kind of sense two objects are deeply equal?
The comparison would be deep, if you passed Array objects.
Non-array objects will not be evaluated deeper than what you get with equals .
So the depth isn't relevant in your case :
Two null values are deeply equal. If both arguments are arrays, the
algorithm in Arrays.deepEquals is used to determine equality.
Otherwise, equality is determined by using the equals method of the
first argument.
Quoted from :
Object.deepEquals
You can refer: Your's Deeply - Why Arrays.deepEquals When We Have Arrays.equals
Arrays.deepEquals looks really deep
From the source, we could understand that Arrays.deepEquals
Loops through the input arrays, gets each pair
Analyses the type of each pair
Delegates the equal deciding logic to one of the overloaded
Arrays.equals if they are one of the primitive arrays
Delegates recursively to Arrays.deepEquals if it is an Object array
Calls the respective object’s equals, for any other object
I used this straight-forward method:
Collection<Integer> aCollection = Arrays.asList(1,2,3,4,5,6);
Integer a = new Integer(5);
if( aCollection.contains(a) )
System.out.println("aCollection contains 5");
Result is "aCollection contains 5". Integers are not unique objects in whole system, but in this case are the "5" in Collection<Integer> and the new Integer(5) in fact references to the same object?
Can I safely assume that any collection will behave this way when calling .contains()?
I am not sure because when comparing references and values by == result is:
3 == new Integer(3)
new Integer(3) != new Integer(3)
new Integer(3) == 3
contains does not compare by reference. new Integer(50000) is different from another call to new Integer(50000). However, firstInt.equals(new Integer(50000)) will return true, hence contains will work. I use higher numbers since interning can happen with lower ones.
0-127 will be put into a fixed pool when performing boxing but not when explicitly creating new objects so you'll have the same reference to the same value, but above that, you have no guarantee of any interning, and references may be to different Integer objects for the same value. Integer.valueOf( will attempt to intern where appropriate, namely always within [-128, 128) and with no specification for or against interning outside this range.
Can I safely assume that any collection will behave this way when calling .contains()?
You can assume that .contains(Object o) will return true if and only if one or more members of the collection satisfies thatmember.equals(o), or if o is null, and there is at least one null member.
Technically:
Returns true if this collection contains the specified element. More
formally, returns true if and only if this collection contains at
least one element e such that (o==null ? e==null : o.equals(e)).
It is defined in JavaDoc:
boolean contains(Object o)
Returns true if this collection contains the specified element. More
formally, returns true if and only if this collection contains at
least one element e such that (o==null ? e==null : o.equals(e)).
In words: If o is null, contains will return true if the collection contains a null element, otherwise it will return true if and only if there is an element that equals() the one you are searching for.
Every call to new Integer(5) will return a different reference, but all the objects are equal to one another according to the equals() method of the Integer class:
Compares this object to the specified object. 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.
.contains() of an collection calls the .equals() method internally.
In your case you are using an Integer object. And an Integer object .equals() might return true in all the cases you have listed.
However that might not be case for a custom object you have say Person.
Now for a collection
Collection<Person> aCollection = Arrays.asList(b,c,d);
Person a = new Person("Abhishek");
may return false. because you have not overridden the .equals() method in your Person class
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example, converting an int to an Integer, a double to a Double, and so on. If the conversion goes the other way, this is called unboxing.
http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Whenever I use equals() method with two different StringBuffer objects, I get the result as false, but when I use equals() method with two different String objects, I get the result as true. Why?
String s=new String("434");
String s1=new String("434");
System.out.println(s.equals(s1));//true
StringBuffer s=new StringBuffer("434");
StringBuffer s1=new StringBuffer("434");
System.out.println(s.equals(s1));//false
StringBuffer does not override equals(). As such, Object.equals() is called, which compare the object identity (the memory address). String does override equals and compare the content.
StringBuffer does not override Object#equals(), so you're experiencing reference identity-based checks rather than value-based checks. As these StringBuilder instances are distinct, each with different memory locations, the base Object#equals() implementation will always return false.
Here's the definition as of Java 6:
public boolean equals(Object obj) {
return (this == obj);
}
See the problem?
At least in my version of the JDK (Sun 1.6), StringBuffer does not implement an equals() method. This means it inherits Object's equals() method, which is the same as ==
If you really want to test two StringBuffers for equality, you could call x.toString().equals(y.toString())
If what you are looking to do is compare the String representations of the two StringBuffer objects, then what you want to do is:
StringBuffer sb1 = new StringBuffer("434");
StringBuffer sb2 = new StringBuffer("434");
if (sb1.toString().equals(sb2.toString())) {
// whatever you want to do if they're equal
} else {
// whatever you want to do if they're not
}
Otherwise, you're comparing for equality of the two StringBuffer objects, not their contents -- in other words, executing Object#equals(), not (the non-existent) StringBuffer#equals().
equals only returns true on StringBuffer objects when the two objects are the same. To compare StringBuffers the way you want, use this:
System.out.println(s.toString().equals(s1.toString());
String s.equals will use the string table to compare the actual strings where as the StringBuffer sb.equals will just use the default implementation of the equals method and just compare the object pointers.
StringBuffer doesn't have it's own implemention of equals method it inherits the equals() method from the object class hence the hashvalues are compared rather than comparing the actual content in the stringBuffer. Hence we have to explicitly cast it to a string object which provides the implementation for equals() method.
The semantics of the String object are such that if two instances are ever observed to contain the same sequence of characters, they will always contain the same sequence of characters and one could--at least from the standpoint of the String object itself--replace all references to one of the strings with references to the other without changing program semantics. Such instances may be considered equivalent, because for all practical purpose, the only information encapsulated in an instance of String is the sequence of characters contained in the target instance.
By contrast, a variable of type StringBuffer encapsulates not just a sequence of characters, but also the identity of a particular instance. If two variables refer to the same instance, changing to the instance referred to by one variable will affect the instance referred to by the other (since it's the same instance). If they refer to different instances, changes to the instance referred to by one will not affect the instance referred to by the other. The decision not to have Java's StringBuffer override equals wasn't a result of laziness, but was rather based upon the fact that StringBuffer objects have a meaningful identity, and disjoint instances always have different identities.