I am trying to implement the .equals method in Android:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
String prdId = product.getProductId();
return productId.equals(prdId);
}
These lines are skipped when I run a debug and single step through it:
Product product = (Product) o;
String prdId = product.getProductId();
And the app crashes with no stacktrace. Please help. Thanks.
This equals methods can possibly yield a NullPointerException if this.productId is null.
You can use Objects.equals() for a null-safe compare:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
String prdId = product.getProductId();
return Objects.equals(productId, prdId);
}
To be sure, we would really need a StackTrace though...
It seems that your issue related to NullPointerException, because productid is null, you have to make sure that the productid is not null before calling productid.equals
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
String prdId = product.getProductId();
return (productId == prdId) || (productId != null &&
productId.equals(prdId)); // null-safe equals
}
Related
#IdClass=(value = TripleKey.class)
class Triple {
String subject;
String predicate;
String object;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Triple triple = (Triple) o;
if (!subject.equals(triple.subject)) return false;
return predicate.equals(triple.predicate);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + subject.hashCode();
result = 31 * result + predicate.hashCode();
return result;
}
}
my objects are:
{
"subject": "http://www.someurl.com/thing/resources/<owner>#SenMLJSON",
"predicate": "probes_in",
"object":"http://sweet.jpl.nasa.gov/2.3/matrSediment.owl#clay"
}
and
{
"subject": "http://www.someurl.com/thing/resources/<owner>#SenMLJSON",
"predicate": "probes_in",
"object":"http://sweet.jpl.nasa.gov/2.3/matrSediment.owl#sand"
}
When I try the following I still have duplicates :
public static List<Triple> mergeTripleLists(List<Triple> oldList, List<Triple> newList) {
Set<Triple> tripleSet = new HashSet<>(oldList);
tripleSet.removeAll(newList);
tripleSet.addAll(newList);
return new ArrayList<>(tripleSet);
}
The problem is in:
if (!super.equals(o)) return false;
If should work after removing it.
The problem is the call to the equals method of the super class which uses object reference to test equality, so remove the line with
!super.equals(o)
You also need to remove the call to the hashCode method of the super class.
I'm studying object oriented programming in Java at my school and I had to do an exercise to compare Circles.
I had the Circle Class with these
private int id;
private String bgColor;
private String fgColor;
And inside it I had to use the equals method to compare two circles (by using these three attributes): a circle is equal to other circle if its radius and the bg and fgColor are the same.
public boolean equals(Object obj) {
boolean found;
if (obj == null) {
found = false;
}
if (getClass() != obj.getClass()) {
found = false;
}
final Circle other = (Circle) obj;
if (Double.doubleToLongBits(this.radius) == Double.doubleToLongBits(other.radius)) {
//found = false;
if (Objects.equals(this.bgColor, other.bgColor)) {
//found = false;
if (Objects.equals(this.fgColor, other.fgColor)) {
return true;
}//end if fgColor
else{
found = false;
}
}//end if bgcolor
else{
found = false;
}
}//end if radius
else{
found = false;
}
return found;
}
But my teacher told me that the code above is "confusing", but I don't understand why.
Do you know a better solution?
My teacher wants that we folow this structure (this case is only comparing one property):
public boolean equals (Object obj)
{
boolean b;
if(obj == null)
{
b = false;
}
else
{
if(this == obj)//same object
{
b = true;
}
else
{
if(obj instanceof Book)
{
Book other = (Book) obj;
b = (this.id == other.id);
}
else
{
b = false;
}
}
}
return b;
}
This is about the most concise version (assuming that radius and colors can't be null). The null check for obj is taken care of by the instanceof test:
public boolean equals(Object obj) {
if( ! (obj instanceof Circle ) )
return false;
Circle rhs = (Circle)obj;
return Double.compare( radius, rhs.radius ) == 0 &&
bgColor.equals( rhs.bgColor ) &&
fgColor.equals( rhs.fgColor );
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
// its a Circle so its safe to case
Circle other = (Circle)obj;
// equals ONLY if 3 conditions are met
if (radius == other.getRadius() &&
bgColor.equals(other.getBgColor()) &&
fgColor.equals(other.getFgColor())){
return true;
}
return false;
}
If you are using a IDE (I hope you do) probably it has an option to generate code for equals method.
Eclipse generates something like:
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Circle other = (Circle) obj;
if (bgColor == null) {
if (other.bgColor != null)
return false;
} else if (!bgColor.equals(other.bgColor))
return false;
if (fgColor == null) {
if (other.fgColor != null)
return false;
} else if (!fgColor.equals(other.fgColor))
return false;
if (Double.doubleToLongBits(radius) != Double.doubleToLongBits(other.radius))
return false;
return true;
}
And don't forget implements hashcode method when you implements equals method and vicecersa.
Rather than having a single return statement consider using multiple return points to simplify the code. This way you do not need extra boolean variables to hold on to the results of prior conditions.
public class Circle {
public double radius;
public String bgColor;
public String fgColor;
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (obj instanceof Circle) {
Circle other = (Circle) obj;
if (Double.compare(this.radius, other.redius) == 0
&& compareStrings(this.fgColor, other.fgColor)
&& compareStrings(this.bgColor, other.bgColor)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
private boolean compareStrings(String a, String b) {
if (a == null && b == null) {
return true;
} else if (a != null) {
return a.equals(b);
} else if (b != null) {
return b.equals(a);
}
return false;
}
}
This solution allows for the possibility that either of the String fgColor or bgColor might be null without throwing a NPE. The String comparison has been extracted into its own function to aid readability and reduce confusion.
As a follow-up to my previous answer:
Writing an equals method that works correctly in the presence of subclassing is extremely non-trivial (see Joshua Bloch's comments in Item 8 of `Effective Java').
Indeed, until relatively recently the was no widely known single method for doing this.
In 2009, the article "How to Write an Equality Method in Java"
by Martin Odersky, Lex Spoon, and Bill Venners shows that this can be achieved in terms of a `canEqual' method.
I am writing an equals method in which two names are considered equal if they have the same first, middle, and last names. However, I keep getting the error
"This class defines a covariant version of the equals() method, but
inherits the normal equals(Object) method defined in the base
java.lang.Object class. The class should probably define a boolean
equals(Object) method."
and when I change it to Object other as the parameter, I get a "no such method" error.
public boolean equals(Name other) {
boolean sameFirstName = firstName.equals(other.firstName);
boolean sameMiddleName = middleName.equals(other.middleName);
boolean sameLastName = lastName.equals(other.lastName);
if (sameFirstName && sameMiddleName && sameLastName) {
return true;
}
return false;
}
You have to use Object type for parameter which called 'other'. Then do instance of checking and casting. Please refer to this answer
If you use Java 7 or higher, you can use this code:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(middleName, person.middleName) &&
Objects.equals(lastName, person.lastName);
}
And there is an automatically generated equals in IDE:
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return !(firstName != null ? !firstName.equals(person.firstName) : person.firstName != null)
&& !(middleName != null ? !middleName.equals(person.middleName) : person.middleName != null)
&& !(lastName != null ? !lastName.equals(person.lastName) : person.lastName != null);
}
Please notice that there should be NPE check as well.
You are overloading the method equals by having a different parameter to type Object. The following should work for you.
#Override
public boolean equals(Object object) {
if(this == object) return true;
if(!(object instanceof Name)) return false;
Name other = (Name) object;
boolean sameFirstName = firstName.equals(other.firstName);
boolean sameMiddleName = middleName.equals(other.middleName);
boolean sameLastName = lastName.equals(other.lastName);
if (sameFirstName && sameMiddleName && sameLastName) {
return true;
}
return false;
}
I am reading the Hashtable's code, and I learned that both Hashtable's key and value can not be null, but its equals method test the situation that value is null or not.
public synchronized boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<K,V> t = (Map<K,V>) o;
if (t.size() != size())
return false;
try {
Iterator<Map.Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Map.Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
if (value == null) { // Can Hashtable's value be null?
if (!(t.get(key)==null && t.containsKey(key)))
return false;
} else {
if (!value.equals(t.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
It is kind of a pattern that is followed throughout to handle the NPE. Consider a simple class
public class HelloWorld {
String data;
}
If you generate hashCode() and equals() you will see this general pattern followed. As in this case
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HelloWorld that = (HelloWorld) o;
if (data != null ? !data.equals(that.data) : that.data != null) return false;
return true;
}
#Override
public int hashCode() {
return data != null ? data.hashCode() : 0;
}
As you can see we always check for null. It is not mandatory but a good programming practice. I understand it makes no sense in the case of Hashtable's but as I mentioned earlier developers must have added this check to maintain a uniform pattern.
Update : As Tim has suggested Since Hashtable is subclassable, it is possible for a subclass to try to support null keys or values. So it is safe to do a null check.
I am developing an Android application which makes use of the ScanResult object. This object is in the form of:
[SSID: __mynetwork__, BSSID: 00:0e:2e:ae:4e:85, capabilities: [WPA-PSK-TKIP][ESS], level: -69, frequency: 2457, timestamp: 117455824743]
How would I override only the equals() method without creating a customer class which extends it in order to compare only the SSID, BSSID, capabilties, level and frequency attributes only? In other words, in the equals method I want to eliminate the timestamp attribute, so that when I compare these two objects, the equals() method would return a true value:
[SSID: __mynetwork__, BSSID: 00:0e:2e:ae:4e:85, capabilities: [WPA-PSK-TKIP][ESS], level: -69, frequency: 2457, timestamp: 117455824743]
[SSID: __mynetwork__, BSSID: 00:0e:2e:ae:4e:85, capabilities: [WPA-PSK-TKIP][ESS], level: -69, frequency: 2457, timestamp: 117460312231]
Note: When I derive a customer class which extends ScanResult I get the following error when I try to implement a constructor: The constructor ScanResult() is not visible
You just have to implement it without checking the fields you want to ignore. Don't forget to override the hashode() too.
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((field1 == null) ? 0 : field1.hashCode());
result = prime * result + ((field2 == null) ? 0 : field2.hashCode());
...etc
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ScanResult other = (ScanResult ) obj;
if (field1 == null) {
if (other.field1 != null)
return false;
} else if (!field1.equals(other.field1))
return false;
if (field2 == null) {
if (other.field2 != null)
return false;
} else if (!field2 .equals(other.field2 ))
return false;
}
... etc
}
This is your Overriden equals() Method....
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ScanResult)) return false;
if(!BSSID.equals(o.BSSID)) return false;
if(!SSID.equals(o.SSID)) return false;
if(!capabilities.equals(o.capabilities)) return false;
if(frequency != o.frequency) return false;
if(level != o.level) return false;
return true;
}
EDIT
Now that the above solution not working, may I suggest:
class ScanResultComparator {
public static boolean equals(ScanResult a, ScanResult b){
if(!a.BSSID.equals(b.BSSID)) return false;
if(!a.SSID.equals(b.SSID)) return false;
if(!a.capabilities.equals(b.capabilities)) return false;
if(a.frequency != b.frequency) return false;
if(a.level != b.level) return false;
return true;
}
}
Extend the ScanResult class and only override the equals() method
class CustomScanResult extends ScanResult {
#Override
public boolean equals(Object o) {
// ... custom logic ...
}
}
simple way use check all variables for true.
example:
public class FtpFile {
public String host;
public String port;
public String fileName;
public String path;
public String username;
public String password;
/**
* Override Equals()
*/
#Override
public boolean equals(Object o) {
try {
if (o == null || getClass() != o.getClass())
return false;
FtpFile p = (FtpFile) o;
return ((host.equals(p.host))
&& (port.equals(p.port))
&& (path.equals(p.path))
&& (username.equals(p.username))
&& (password.equals(p.password)));
} catch (Exception ex) {
return false;
}
}
}