Equals method on list of lists - java

Let this be a definition of a matrix:
private List<<List<Object>> lines;
public boolean equals(Object o){
if(this==o)
return true;
if((o==null) || (this.getClass()!=o.getClass()))
return false;
Matrix m = (Matrix) o;
return ????;
}
how can I compare all those lines and columns.
Can I just use
return this.lines.equals(o.getLines());
??
Thanks

More or less, though that exact code doesn't quite work.
From the List.equals javadoc:
Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).)
You can indeed use this method to determine equality, but you need to cast o first. This is a safe cast because you already checked the class (though you might consider using instanceof Matrix instead).
return this.lines.equals(((Matrix)o).getLines());

Related

Overide equals method in class with aggregation Arraylist

I need to override equals() and hashCode() methods in Java class. But this class contains a list of objects. How should I implement the part of the code with comparing ArrayList field?
The code looks like:
public class FirstClass {
private List<SecondClass> list = new ArrayList<>();
equals() {
//how i should implement equals for list field?
}
hashCode() {
}
}
I can only add that SecondClass has well-working equals and hashCode methods.
I know about symmetric, transition and others important things, but I only want to focus on this problem with ArrayList field.
ArrayList (and any List implementation) is required to override equals and hashCode properly, as stated in the List javadoc:
boolean java.util.List.equals(Object o)
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface.
int java.util.List.hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the following calculation:
int hashCode = 1;
for (E e : list) {hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());}
Therefore all you need is to call list.equals() and list.hashCode().
public class FirstClass
{
private List<SecondClass> list = new ArrayList<>();
#Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof FirstClass))
return false;
FirstClass fc = (FirstClass) other;
return list.equals(fc.list);
}
#Override
public int hashCode() {
return list.hashCode ();
}
}
This is assuming list can never be null. Otherwise, some additional checks must be added.

Java - Do two HashSets change similarly overtime?

I already looked into different questions but these usually ask about consistency or ordering, while I am interested into ordering of two HashSets containing the same elements at the same time.
I want to create a HashSet of HashSets containing integers. Over time I will put HashSets of size 3 in this bigger HashSet and I will want to see if a newly created HashSet is already contained within the bigger HashSet.
Now my question is will it always find duplicates or can the ordering of two HashSets with the same elements be different?
I am conflicted as they use the same hashcode() function but does that mean they will always be the same?
HashSet<HashSet<Integer>> test = new HashSet<>();
HashSet<Integer> one = new HashSet<>();
one.add(1);
one.add(2);
one.add(5);
test.add(one);
HashSet<Integer> two = new HashSet<>();
two.add(5);
two.add(1);
two.add(2);
//Some other stuff that runs over time
System.out.println(test.contains(two));
Above code tries to illustrate what I mean, does this always return true? (Keep in mind I might initialise another HashSet with the same elements and try the contains again)
Yes, the above always returns true. Sets have no order, and when you test whether two Sets are equal to each other, you are checking that they have the same elements. Order has no meaning.
To elaborate, test.contains(two) will return true, if an only if test contains an element having the same hashCode() as two which is equal to two (according to the equals method).
Two sets s1 and s2 that have the same elements have the same hashCode() and s1.equals(s2) returns true.
This is required by the contract of equals and hashCode of the Set interface:
equals
Compares the specified object with this set for equality. Returns true if the specified object is also a set, the two sets have the same size, and every member of the specified set is contained in this set (or equivalently, every member of this set is contained in the specified set). This definition ensures that the equals method works properly across different implementations of the set interface.
hashCode
Returns the hash code value for this set. The hash code of a set is defined to be the sum of the hash codes of the elements in the set, where the hash code of a null element is defined to be zero. This ensures that s1.equals(s2) implies that s1.hashCode()==s2.hashCode() for any two sets s1 and s2, as required by the general contract of Object.hashCode.
As you can see, one and two don't even have to use the same implementation of the Set interface in order for test.contains(two) to return true. They just have to contain the same elements.
The key property of sets is about uniqueness of keys.
By "default", insertion order doesn't matter at all.
A linked LinkedHashSet guarantees to you that when iterating, you get the elements always in the same order (the one used for inserting them). But even then, when comparing such sets, it is still only about their content, not that insertion order part.
In other words: no matter what (default) implementation of the Set interface you are using, you should always see consistent behavior. Of course you free to implement your own Set and to violate that contract, but well, violating contracts leads to violated contracts, aka bugs.
You can look for yourself, this is open source code:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
You can easily see that the hashcode will be the sum of the hashcode of the elements, so it is not affected by any order and that equals use containsAll(...) so also here the order doesn't matter.

Java (ArrayList check with object's int)

I have to make an ArrayList that contains an object, the object has one int for year lets say 1
and I don't what another object with the same year 1.
If one object has the int = 1 , i dont want another object with that int(1) in my list.
i want to deny it.
Should I try using equal?
something like
#Override
public boolean equals(Object o){
Object object = (Object)o;
return this.getInt.equals(object.getInt());
}
Either use a Set...which explicitly disallows duplicates, or check if the list contains the element on insertion.
#Override
public boolean add(T element) {
if(contains(element)) {
return false;
} else {
return super.add(element);
}
}
Overriding equals wouldn't get you very far, as you'd be overriding it for the List itself (i.e. you'd be checking if two lists were equal).
Perhaps you can try using a HashMap linked that links that "int" with the object. That could be:
Map<Integer, Object> map = new HashMap<>();
map.put(object.getInt(), object);
...
//Each time you put a new object you could try this:
if(!map.contains(object.getInt()))
map.put(object.getInt, object);
//And you can retrieve your object by an int
int a = 1;
Object obj = map.get(1);
In this case, as the value is of type int, you can use equal operator.
public boolean equals(Object o){
Object object = (Object)o;
return (this.getInt()==object.getInt());
}
For this kind of requirement, ArrayList is not suggestible. As mentioned in the other answers try using HashMap.
Yes, you can. When you call
myArrayList.contains(myObejct);
the ArrayList will invode myObejct's equals method. So you can tell if the object is already in you list.
And I think you can change you method a little,
#Override
public boolean equals(Object o){
if (!(o instanceof YourClass))
return false;
YourClass object = (YourClass)o;
return this.getInt.equals(object.getInt());
}
because if you don't, the method "getInt" might cause a MethodNotFound exception.
Well, that is one way to approach the problem.
Your equals will probably work provided that you change Object object = (Object)o; to cast to the real class.
However, equals ought to cope with the case where o is not of the expected type. The contract requires you should return false rather than throwing a ClassCastException ...
You would then use list.contains(o) to test if an object with the same int value exists in the list. For example:
if (!list.contains(o)) {
list.add(o);
}
But when you override equals, it is best practice to also override hashcode ... so that your class continues to satisfy the equals / hashcode invariants. (If you neglect to do that, hash-based data structures will break for your class.)
However, this won't scale well, because the contains operation on an ArrayList has to test each element in the list, one at a time. As the list gets longer, the contains call takes longer ... in direct proportion; i.e. O(N) ... using Big O complexity notation.
So it may be better to use a Set implementation of some kind instead on ArrayList. Fepending on which set implementation you choose, you will get complexity of O(1) or O(logN). But the catch is that you will either have to to implement hashcode (for a HashSet or LinkedHashSet), or implement either Comparable or a Comparator (for a TreeSet).

Java ArrayList Contain always return false although it contain the same value

This is my Hole Class
class Hole {
public int a;
public int b;
Hole(int a, int b) {
this.a = a;
this.b = b;
}
So i adding an ArrayList that contain several several hole
public void checkPathLoop(int x, int y) {
//rough code
ArrayList<Hole> leftFlowInnerHole = new ArrayList<>();
//left holes rules
leftFlowInnerHole.add(new Hole(0, 1));
leftFlowInnerHole.add(new Hole(1, 5));
leftFlowInnerHole.add(new Hole(5, 4));
leftFlowInnerHole.add(new Hole(0, 4));
when i add
Hole userInputHole = new Hole(0,1);
System.out.print(leftFlowInnerHole.contain(userInputHole));
it always return false !! it suppose to return true.
Is there anything i miss ??
Thank you in advance
You need to override the equals method herited from the Object class (and hence also hashCode to respect the contract, see Why do I need to override the equals and hashCode methods in Java? ) in your Hole class.
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)).
Basically the default equals implementation is an == comparison between the two objects
public boolean equals(Object obj) {
return (this == obj);
}
Since you created two different objects, while they have the same value as attributes they're two distincts objects and hence this == obj returns false.
If you did :
Hole a = new Hole(0,1);
leftFlowInnerHole.add(a);
System.out.print(leftFlowInnerHole.contains(a));
You'll see that it outputs true.
You should overide the equals method of the Hole class:
#Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Hole)) {
return false;
}
Hole other = (Hole) obj;
return a == other.a && b == other.b;
}
contains() method checks the equal() method on Object while checking .
You have to ovveride equals method in order to make it work.
public 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)).
Edit:
If you not ovveriding equals method, Then default Object equals method executes and, as per docs of Equals method
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).
So your userInputHole == leftFlowInnerHole is always false as they are pointing to different instances.
Hence to avoid the default implementation ,you just ovveride that equals in yout class and provide your implementation.
An efficient equals(Object o) implementation
This is not working
if(priceidslist.contains(extraId)){
//Not working
}
I just added this lines for checking that condition in (for -loop ),then its working fine
String gh = String.valueOf(priceidslist.get(j));
if(gh.equals(extraId)){
rw.put("extraPrice",pricelist.get(j));
}

Why does my custom equals method (doubles and integers) not work?

I have a custom equals to check the equality of my object called Pair.
class Pair implements Comparable <Parr> {
double coef;
int power;
Pair(double a, int b) {
coef = a;
power = b;
}
My custom equals method is (located in class pair):
#Override
public boolean equals(Object o) {
if (!(o instanceof Pair))
return false;
Pair that = (Pair) o;
return that.coef == this.coef && that.power == this.power;
}
I've checked with print my object if the objects are the same, and they are indeed the same.
1.0 1 2.0 0
1.0 1 2.0 0
I call my custom equals from a different file, called Test.
class Test {
public static void main(String[] args) {
orig = pol1.differentiate().integrate();
System.out.print(orig);
if (orig.equals(pol1))
System.out.println(" (is equal.)");
else
System.out.println(" (is not equal.)");
And my class Polynomial, which is an arraylist with objects of Pair inside.
class Polynominal implements PolynominalInterface {
ArrayList<Pair> terms = new ArrayList<Pair>();
I looked on the internet, and I found that I cannot use == in my Equals method, but I'm using Intergers and Doubles, so equals() would not work.
Can anyone point me in the right direction?
If orig and pol1 are instances of Polynomial then this
if (orig.equals(pol1))
would only work if you implement Polynomial#equals() as well; which would iterate the two ArrayLists and make sure individual Pairs are equal (using Pair#equals() of course).
Ok, thanks to Ravi Thapliyal I found the solution.
After adding an custom equals method in my Polynominal class, the problem was fixed.
#Override
public boolean equals(Object o) {
if (!(o instanceof Polynomial))
return false;
Polynomial that = (Polynomial) o;
return that.terms.equals(terms);
}
Use the Double.compare(double, double) method instead of ==.
Floating point comparison is "fuzzy" in Java.
You would need to implement a Polynomail.equals() method something like the following:
public boolean equals(Object o) {
if (!(o instanceof Polynomial)) return false;
Polynomial other = (Polynomial) o;
if (this.terms==null && other.terms==null) return true;
// A suitable equals() method already exists for ArrayList, so we can use that
// this will in turn use Pair.equals() which looks OK to me
if (this.terms!=null && other.terms!=null) return this.terms.equals(other.terms);
return false;
}
Two issues come to mind: the first is that the default hashCode() method will seldom return the same value for any two distinct object instances, regardless of their contents. This is a good thing if the equals() method will never report two distinct object instances as equal, but is a bad thing if it will. Every object which overrides Object.equals() should also override Object.hashCode() so that if x.equals(y), then x.hashCode()==y.hashCode(); this is important because even non-hashed generic collections may use objects' hash codes to expedite comparisons. If you don't want to write a "real" hash function, simply pick some arbitrary integer and have your type's hashCode() method always return that. Any hashed collection into which your type is stored will perform slowly, but all collections into which it is stored should behave correctly.
The second issue you may be seeing is that floating-point comparisons are sometimes dodgy. Two numbers may be essentially equal but compare unequal. Worse, the IEEE decided for whatever reason that floating-point "not-a-number" values should compare unequal to everything--even themselves.
Factoring both of these issues together, I would suggest that you might want to rewrite your equals method to chain to the equals method of double. Further, if neither field of your object will be modified while it's stored in a collection, have your hashCode() method compute the hashCode of the int, multiply it by some large odd number, and then add or xor that with the hashCode of the double. If your object might be modified while stored in a collection, have hashCode() return a constant. If you don't override hashCode() you cannot expect the equals methods of any objects which contain yours to work correctly.

Categories