简体   繁体   中英

2D Arrays & Matrices - Java

I have to admit, I'm a little stuck on this equals method. I think I'm pretty close because the first JUnit test that we're given passes but when I make a test for one that should return false, I fail and it returns true. Can I get some assistance on this, please?

public class Matrix {

// the dimensions of the matrix
private int numRows;
private int numColumns;

// the internal storage for the matrix elements 
private int data[][];

/**
 * @param d - the raw 2D array containing the initial values for the Matrix.
 */
public Matrix(int d[][])
{
    // d.length is the number of 1D arrays in the 2D array
    numRows = d.length; 
    if(numRows == 0)
        numColumns = 0;
    else
        numColumns = d[0].length; // d[0] is the first 1D array
    
    // create a new matrix to hold the data
    data = new int[numRows][numColumns]; 
    
    // copy the data over
    for(int i=0; i < numRows; i++) 
        for(int j=0; j < numColumns; j++)
            data[i][j] = d[i][j];
}



/**
 * Determines whether this Matrix is equal to another object.
 * @param o - the other object to compare to, which may not be a Matrix
 */
@Override // instruct the compiler that we intend for this method to override the superclass' (Object) version
public boolean equals(Object o)
{
    // make sure the Object we're comparing to is a Matrix
    if(!(o instanceof Matrix))
        return false;
    
    // if the above was not true, we know it's safe to treat 'o' as a Matrix
    Matrix m = (Matrix)o;
    
    /*
     * TODO: replace the below return statement with the correct code. 
     *  
     *  Returns true if this Matrix is equal to the input Matrix; returns false otherwise
     */ 
    boolean matches = true;
    
    if(o instanceof Matrix)
        for(int i = 0; i < data[i].length; i++)
            for(int j = 0; j < data[j].length; j++)
                if(o[i][j] != m[i][j])
                    matches = false;
    
    return matches;
}

The problem is here:

if(o instanceof Matrix)
    for(int i = 0; i < data[i].length; i++)
        for(int j = 0; i < data[j].length; j++)
            if(o[i][j] == m[i][j])
                return true;

You're looping over every element in the array and when you found any element that matches with the element in the other array, you're returning true . I would create a boolean (initially set to true ) and when I found an element that doesn't match, I would set the boolean to false and return the boolean at the end of the method:

boolean matches = true;

if(o instanceof Matrix)
    for(int i = 0; i < data[i].length; i++)
        for(int j = 0; i < data[j].length; j++)
            if(o[i][j] != m[i][j])
                matches = false;

return matches;

This author asked nearly the same question . To simplify things, I'll answer here instead of there.

If I were a teacher, these are the things I would point out, step-by-step:

  1. This won't compile: if(o[i][j] != m[i][j]) Neither o nor m is an array, and so can't have subscripts.

  2. Suppose we make this change: if (o.data[i][j].= m.data[i][j]) . Now o.data[i][j] won't compile, because o is an Object type, which has no member named data .

  3. We could use a class cast like this: if (((Matrix) o).data[i][j].= m.data[i][j]) . Now, it will compile. But, the code above has this line: Matrix m = (Matrix)o; So, o and m point to the same object . As long as that's the case, ((Matrix) o).data[i][j] == m.data[i][j] will always be true .

  4. To fix the above, we need to use two different instances of Matrix . We get one instance from the parameter: o . The second one is implicit, but has a name: this . So, this is what we want for our comparison: if(this.data[i][j].= m.data[i][j])

Here are some other comments, outside the scope of your question:

Once you have determined that the contents of the two instances of Matrix do not match, you can escape the for loops with break . It could save time if you are processing large matrices.

@Override
public boolean equals (Object o) {
    if (o == this) return true;
    if (o == null) return false;
    if(!(o instanceof Matrix)) return false;
    

In general, it is a good idea to begin .equals methods with the above 3 tests.

     Matrix m = (Matrix)o;  
    

When overriding .equals , it's strongly recommended that hascode () be overridden also. So, please think about the following line:

    if (m.hashCode() != this.hashCode()) return false;

If hashcode () is properly implemented, two objects returning different hash codes are guaranteed to return false for .equals . However, two objects returning the same hash code could return either true or false for .equals . So, if the hascode() test returns true, we keep testing:

// two matrices can have different sizes. Comparing the sizes early
// will not only save time, it  will guard against throwing 
// an `ArrayIndexOutOfBoundsException` when the sizes are different

if (    m.numRows    != this.numRows 
     || m.numColumns != this.numColumns) return false;

 boolean matches = true;

 outer: for(int i = 0; i < numRows; i++) {
           for(int j = 0; numColumns; j++) {
               if(this.data[i][j] != m.data[i][j]) {
                  matches = false;
                  if (!matches)
                    break outer;
            }
        }            
    }        
return matches;

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM