Override equals() method only of a Java object - java

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;
}
}
}

Related

Abstract Class Java

I need to write abstract class, which looks like this.
public abstract class Value {
public abstract String toString();
public abstract Value add(Value v);
public abstract Value sub(Value v);
public abstract boolean eq(Value v);
public abstract boolean lte(Value v);
public abstract boolean gte(Value v);
public abstract boolean neq(Value v);
public abstract boolean equals(Object other);
public abstract int hashCode();
public abstract Value create(String s);
}
Now I need to make few classe, which inherit from that one. I started from Int class and implemented it like this:
public class Int extends Value {
int val;
public String toString() {
String toStr = Integer.toString(val);
return toStr;
}
public Int add(Value v) {
Int result = new Int();
if(v instanceof Int) {
Int temp = (Int) v;
result.val = val + temp.val;
}
return result;
}
public Int sub(Value v) {
Int result = new Int();
if(v instanceof Int) {
Int temp = (Int) v;
result.val = val - temp.val;
}
return result;
}
public boolean eq(Value o) {
if(this == o) return true;
if(this == null) return false;
if(getClass() != o.getClass()) return false;
Int other = (Int) o;
return toString() == other.toString();
}
public boolean lte(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return this.val < temp.val;
}
return false;
}
public boolean gte(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return this.val > temp.val;
}
return false;
}
public boolean neq(Value v) {
if(v instanceof Int) {
Int temp = (Int) v;
return !eq(temp);
}
return true;
}
public boolean equals(Object o) {
if(this == o) return true;
if(this == null) return false;
if(getClass() != o.getClass()) return false;
Int other = (Int) o;
return toString() == other.toString();
}
public int hashCode() {
Integer hash = val;
return hash.hashCode();
}
public Int create(String s) {
val = Integer.parseInt(s);
return this;
}
}
Everything is compiling and working, but I have no clue if my hashcode() function and equals() are good. Furthermore i want to use create() to make objects like this:
getInstance().create("1234");
Is my method also sufficient?
Everything is compiling and working, but I have no clue if my hashcode() function and equals() are good.
Your equals() should compare int val and not result of toString() of compared objects (this.val == other.val).
Your hashCode() looks good, though I would add #Override to it (same with equals()).
Furthermore i want to use create() to make objects like this: getInstance().create("1234");
Looking at its implementation, it looks fine (i.e. would work according to your needs):
public Int create(String s) {
val = Integer.parseInt(s);
return this;
}
though I don't think you really want to use it with getInstance(). Simply Int.create() would be enough:
public static Int create(String s) {
val = Integer.parseInt(s);
return new Int(val);
}
Note that you would need a private constructor.
Also, as someone noted in the comments, consider using generics instead of inheritance.
The hashCode() method is fine (although I'd add an #Override annotation, just to make the code easier to maintain and avoid mistakes), but the equals(Object) definitely isn't.
Following the logic you have in place, == isn't the right way to compare strings. You should use equals instead (see, e.g., How do I compare strings in Java?). In addition, as Joakim Danielson noted in the comments, this can never be null - you should check if o is null instead:
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if(getClass() != o.getClass()) {
return false;
}
Int other = (Int) o;
return toString().equals(other.toString()); // Here!
}
But in all fairness, there's no reason to use toString - you could just compare the internal val:
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if(getClass() != o.getClass()) {
return false;
}
Int other = (Int) o;
return val == other.val; // Here!
}
First when you override Methods please do it with #Override Annotation. Then i would implement your equals method in another way. Just do return this.val == other.val instead of doing this.toString() == other.toString(). Your toString() method implementation is ok. Your hashCode is good as well. But please remove that create method. Use a constructor instead.
Can I implement equals() method using eq() like this ?
public boolean equals(Object o) {
Value compare = (Value) o;
return eq(compare);
}

Equals method does not return true for same object

#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.

How do I implement equals for generic types?

Suppose I have a generic container type like this:
public final class Container<T> {
public final T t;
public Container(final T t) {
this.t = t;
}
}
I want to implement equals such that this passes:
final Container<Object> a = new Container<>("Hello");
final Container<String> b = new Container<>("Hello");
assertNotEquals(a, b);
The instances a and b should be different because their type parameter T is different.
However, due to erasure, this is tricky to do. This implementation, for example, is incorrect:
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj instanceof Container<?>) {
final Container<?> other = (Container<?>)obj;
return Objects.equals(this.t, other.t);
}
return false;
}
I expect that I will need to store some kind of token for T.
How do I implement equals for generic types?
This does not answer the question.
you can modify a little the Container class and add this field:
public final Class<T> ct;
with that and the equals override then
System.out.println(a.equals(b));
will return false because the equals method will check Class<String> vs Class<Object>
class Container<T> {
public final T t;
public final Class<T> ct;
public Container(final T t, Class<T> ct) {
this.t = t;
this.ct = ct;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + ((ct == null) ? 0 : ct.hashCode());
result = (prime * result) + ((t == null) ? 0 : t.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (ct == null) {
if (other.ct != null)
return false;
} else if (!ct.equals(other.ct))
return false;
if (t == null) {
if (other.t != null)
return false;
} else if (!t.equals(other.t))
return false;
return true;
}
}

Class equals method is confusing

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.

how to subtract ArrayList using removeall() in java?

I have array list in java:
List<Correction> Auv=new ArrayList<>();
List<Correction> Produv=new ArrayList<>();
then I want to substract Produv value by Auv, here's an example:
Produv.add(new Correction("a","b"));
Produv.add(new Correction("a","c"));
Produv.add(new Correction("b","d"));
Produv.add(new Correction("b","c"));
Auv.add(new Correction("c","a"));
Auv.add(new Correction("b","c"));
Produv.removeall(Auv);
but nothing subtracted, the array still contain it initial value, is there any way to do this?
I try to override equals(), and still got the same result
here the code of my Correction class:
public class Correction {
private String node0;
private String node1;
public Correction(String node0, String node1) {
this.node0 = node0;
this.node1 = node1;
}
public void setNode0(String node0){
this.node0=node0;
}
public void setNode1(String node1){
this.node1=node1;
}
public String getNode0(){
return node0;
}
public String getNode1(){
return node1;
}
#Override
public boolean equals(Object object){
boolean same = false;
if (object != null && object instanceof Correction)
{
same = this.node0 == ((Correction) object).node1 && this.node1 == ((Correction) object).node1;
}
return same;
}
}
Solved!!
it just simply a mistake on overriding equals() method(thank's guys)
here my correction:
#Override
public boolean equals(Object object){
boolean same = false;
if (object != null && object instanceof Correction)
{
same = (this.node0 == ((Correction) object).node1 && this.node1 == ((Correction) object).node0)||(this.node0 == ((Correction) object).node0 && this.node1 == ((Correction) object).node1);
}
return same;
}
Your equals method looks wrong. It makes more sense to compare this.node0 to ((Correction) object).node0.
I think it should be:
public boolean equals(Object object){
boolean same = false;
if (object != null && object instanceof Correction)
{
same = this.node0.equals(((Correction) object).node0) && this.node1.equals(((Correction) object).node1);
}
return same;
}
Also, is this a typo?
Auv.add("c","a");
Auv.add("b","c");
It should probably be :
Auv.add(new Correction ("c","a"));
Auv.add(new Correction ("b","c"));

Categories