equals methods when using arrays java - java

For my equals method that checks to see if two arrays are equal, does the first method "equals" actually check if the two arrays are equal or only tests the memory addresses? Or should I include both?
public boolean equals(Object otherObject)
{
if (otherObject == null)
{
return false;
}
else if (getClass() != otherObject.getClass())
{
return false;
}
else
{
RegressionModel otherRegressionModel = (RegressionModel)otherObject;
return (xValues == (otherRegressionModel.xValues) && yValues == (otherRegressionModel.yValues));
}
}
OR
public static boolean equalArrays(double[] x, double[] y)
{
if(x.length != y.length)
{
return false;
}
else
{
for(int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}
}

the =/!= operator compares arrays based upon their reference, and not their content. Clearly two arrays may have the same elements, except they are still two distinct objects that are created in the memory. The arrays are two references. Therefore your second method should be applied, because it compares the actual elements inside the two arrays. Also you don't need your else statement.
public static boolean equalArrays(double[] x, double[] y)
{
if(x.length != y.length)
{
return false;
}
for (int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}

One more check can also be applied on first equals method where it can see both array has an same reference or not. Then other comparison can be done. In second method it always check the element of an array, even if both an reference of same array. so in terms of performance it will take time.
public boolean equals(Object otherObject)
{
if (otherObject == null)
{
return false;
}
else if (getClass() != otherObject.getClass())
{
return false;
} else if (this != otherObject)
return false;
}
else
{
RegressionModel otherRegressionModel = (RegressionModel)otherObject;
return (xValues == (otherRegressionModel.xValues) && yValues == (otherRegressionModel.yValues));
}
}

Adding to #Henry's answer, before comparing lengths of the two given arrays you should make sure that neither of them are null so that you don't get a NullPointerException.
You might also want to compare the references of the arrays before looping through their elements.
Something like this:
public static boolean equalArrays(double[] x, double[] y)
{
if (x == null || y == null || x.length != y.length)
{
//NOTE: That if both x and y are null we return false despite the fact that you could argue that they are equal
return false;
}
if (x == y)
{
return true;
}
for (int index = 0; index < x.length; index++)
{
if (x[index] != y[index])
{
return false;
}
}
return true;
}

Related

Loop: This method must return a result of type boolean

This is the error I get:
This method must return a result of type boolean
And this is the code:
public boolean seleccionar(Aeronave otra) {
for (int i = 0; i < this.as.length; i++) {
if (otra != null && !otra.equals(this.as[i]) && otra.amenazadaPor(this.as[i])) {
return true;
} else {
return false;
}
}
}
Add a return false before the last brace. Your function doesn't return anything if this.as.length == 0, and Java is giving a compile error because of that.
The issue is that it is possible that the for-loop will loop through all elements and eventually reach the end and no result is returned. In this case we return false to ensure this.
public boolean seleccionar (Aeronave otra) {
for (int i=0; i < this.as.length; i++) {
if (otra !=null && !otra.equals(this.as[i]) && otra.amenazadaPor(this.as[i])) {
return true;
}
}
return false;
}
Your code will exit on first loop element. But when array this.as is empty, so loop will not execute, then your function is missing a return value -therefore compiler does not allow this.
To solve this issue, simply move return false after the loop ends.
public boolean seleccionar (Aeronave otra) {
for (int i=0; i < this.as.length; i++) {
if (otra !=null && !otra.equals(this.as[i]) && otra.amenazadaPor(this.as[i])) {
return true;
}
}
return false; // if no elements are matching loop condition, return false
}}

are arrays equal method in java

im a newbie, i need to write a method that check if 2 arrays are equal in the values and order, if they are print true, else false
this is what i wrote and the result always true, if i try printing the values that the function recieve in the arrays for some reason they are all 0.
public static boolean areArraysEqual(int[] firstArr, int[] secArr) {
firstArr = new int[N];
secArr = new int[N];
System.out.println(firstArr.length);
if(firstArr.length != secArr.length){
return false;
}
if(firstArr == null || secArr == null){
return false;
}
for(int i = 0; i < firstArr.length; i++) {
if(firstArr[i] != secArr[i]) {
return false;
}
}
return true;
}
When you try to re-allocate the arguments firstArr and secArr, the original array contents get lost.
No need to re-allocte firstArr and secArr, since in java, array objects are passed by value, they can be used as-is for its contents.
The following code snippet is good enough:
public static boolean areArraysEqual(int[] firstArr, int[] secArr) {
if(firstArr == null || secArr == null || firstArr.length != secArr.length){
return false;
}
for(int i = 0; i < firstArr.length; i++) {
if(firstArr[i] != secArr[i]) {
return false;
}
}
return true;
}
You are creating two new arrays, which are initialized to all zeros with
firstArr = new int[N];
secArr = new int[N];
When you call areArraysEqual(int[] firstArr, int[] secArr) you are supplying two arrays already, there is no reason to create new ones.
Removing those two lines should get you going.
The issue with your code is that you are re-declaring the array. Remove firstArr = new int[N]; and secArr = new int[N]; from your code. Then it should work fine.
public static boolean areArraysEqual(int[] firstArr, int[] secArr) {
System.out.println(firstArr.length);
if(firstArr.length != secArr.length){
return false;
}
if(firstArr == null || secArr == null){
return false;
}
for(int i = 0; i < firstArr.length; i++) {
if(firstArr[i] != secArr[i]) {
return false;
}
}
return true;
}
Side note: If this is not for academic/competitive purpose use Array.equals(firstArr, secArr)
Nothing the already submitted answers don't cover, but you've got far too much code written for this. Try this:
public boolean compareArrays(int[] arr1, int[] arr2) {
if (Arrays.equals(arr1, arr2)) {
return true;
}
return false;
}
Arrays.equals covers order and size, no need to check for nulls either, that should be handled by the caller, after all, null does equal null and there for the arrays are equal.

Java equals method does not work as intended

pieces instance is a List that contains class Piece. Piece object contains two instance variables that resemble coordinate int x and int y. However, when I tried these methods, the second method does not return true if the parameter piece is already inside the pieces object. I have generated an equal method on the class Piece. not sure why the second method does not work.
public boolean alreadyContainsCoordinate1(Piece piece) {
for (int i = 0; i < getLength(); i++) {
if (pieces.get(i).getX() == piece.getX() && pieces.get(i).getY() == piece.getY()) {
return true;
}
}
return false;
}
public boolean alreadyContainsThisCoordinate2(Piece piece) {
for (Piece body : pieces) {
if (body.equals(piece)) {
return true;
}
}
return false;
}
Your second alreadyContainsThisCoordinate2() method is probably using the default equals() method for objects, which compares references, not the contents of your particular object. You may try to override equals as follows:
#Override
public boolean equals(Object o) {
if (!(o instanceof Piece)) {
return false;
}
Piece p = (Piece)o;
return this.getX() == p.getX() && this.getY() == p.getY();
}

How to handle null values when doing Collections.sort() with nested objects?

What is the best way to deal with null values, when doing Collections.sort() on nested objects?
I'd like to sort a couple of objects, basically applying this rule:
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
However, any of these objects can be null (i.e. invoice position, invoice and invoice number).
public class InvoicePos {
private Invoice invoice = null;
// ...
}
public class Invoice {
private String invoiceNo = "";
// ...
}
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
For clarification: I'm aware that my above example may raise NullPointerExceptions. Currently I'm doing the following and basically, I questioned myself, if there is any smarter approach.
Collections.sort(allInvoicePositions, new Comparator<InvoicePos>() {
#Override
public int compare(final InvoicePos invoicePosOne, final InvoicePos invoicePosTwo) {
if (null == invoicePosOne && null == invoicePosTwo) {
return 0;
}
if (null == invoicePosOne) {
return -1;
}
if (null == invoicePosTwo) {
return 1;
}
if (null == invoicePosOne.getInvoice() && null == invoicePosTwo.getInvoice()) {
return 0;
}
if (null == invoicePosOne.getInvoice()) {
return -1;
}
if (null == invoicePosTwo.getInvoice()) {
return 1;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo() && null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 0;
}
if (null == invoicePosOne.getInvoice().getInvoiceNo()) {
return -1;
}
if (null == invoicePosTwo.getInvoice().getInvoiceNo()) {
return 1;
}
return invoicePosOne.getInvoice().getInvoiceNo().compareTo(invoicePosTwo.getInvoice().getInvoiceNo());
}
});
There is something called as NullComparator in org.apache.commons.collections.jar.
This might help you https://commons.apache.org/proper/commons-collections/javadocs/api-2.1.1/org/apache/commons/collections/comparators/NullComparator.html.
Do I have do do explicit null-checks on all my objects or is there an approach with less writing?
If these values don't represent anything in your collection, then the best thing you can do is avoid them; don't allow inserting them, so you won't have to handle them when comparing items.
If you insist to have them, then you must check if they're null to avoid NullPointerException.
If you have null values then you need to handle them explicitly and in a consistent way so to have a valid ordering relation. That is, something like:
compare (a, b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return +1;
return comp(a,b);
}
Don't be tempted to do something like:
compare (a, b) {
if (a == null || b == null) return -1;
return comp(a,b);
}
which would break the ordering relation.

Why is SparseIntArray.equals(Object) not working?

I am using a SparseIntArray and I am puzzled by this behavior:
public static SparseIntArray getArray()
{
SparseIntArray result = new SparseIntArray();
result.append(0, 99);
result.append(1, 988);
result.append(2, 636);
return result;
}
public static void testArray()
{
SparseIntArray first = getArray();
SparseIntArray second = getArray();
if( first.equals(second) )
{
Log.v(TAG,"first "+first.toString()+" == second "+second.toString());
}
else
{
Log.v(TAG,"first "+first.toString()+" != second "+second.toString());
}
}
Output:
11-06 14:53:15.011: V/fileName(6709): first {0=99, 1=988, 2=636} != second {0=99, 1=988, 2=636}
I know that using == between two objects will compare the object addresses, which in this case are different, but here I am using SparseIntArray.equals(Object other) and the intended result is not unexpected.
I am sure I can roll my own compare method, but it sounds kind of silly. What is the point of having a base class Object.equals(Object other) method if we cant rely on it?
Can someone point to any mistake?
I just searched for the code of SparseIntArray. If you are referring to android.util.SparseIntArray, it doesn't override equals, which means it uses the default implementation of Object class, which compares the references.
What is the point for having a base class Object.equals(Object other) method if we cant rely on it?
Actually, you can't rely of the base class Object.equals, since it does precisely what you don't want to do:
public boolean equals(Object obj)
{
return (this == obj);
}
It's up to the writers of any class to decide whether to override equals and give a different implementation.
#Eran is right, Object.equals(Object) does not cut it.
I have made a simple static method to compare two instances
public static boolean compareSame( SparseIntArray first, SparseIntArray second )
{
// compare null
if( first == null )
{
return (second == null);
}
if( second == null )
{
return false;
}
// compare count
int count = first.size();
if( second.size() != count )
{
return false;
}
// for each pair
for( int index = 0; index < count; ++index )
{
// compare key
int key = first.keyAt(index);
if( key != second.keyAt(index))
{
return false;
}
// compare value
int value = first.valueAt(index);
if( second.valueAt(index) != value)
{
return false;
}
}
return true;
}
I will probably end up deriving my own version of SparseIntArray and override the equals method, I think this is more clean.
[EDIT] Here is the code for an sub-class implementing equals
import android.util.SparseIntArray;
public class SparseIntArrayComparable extends SparseIntArray {
#Override
public boolean equals( Object obj ) {
if( obj instanceof SparseIntArray ) {
SparseIntArray other = (SparseIntArray)obj;
// compare count
int count = size();
if( count != other.size() )
return false;
// for each pair
for( int index = 0; index < count; ++index ) {
if( keyAt(index) != other.keyAt(index))
return false;
if( valueAt(index) != other.valueAt(index) )
return false;
}
return true;
}
else
return false;
}
}

Categories