### Question:
KeyedObjects2D implements Cloneable, Serializable { @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof KeyedObjects2D)) { return false; } KeyedObjects2D that = (KeyedObjects2D) obj; if (!getRowKeys().equals(that.getRowKeys())) { return false; } if (!getColumnKeys().equals(that.getColumnKeys())) { return false; } int rowCount = getRowCount(); if (rowCount != that.getRowCount()) { return false; } int colCount = getColumnCount(); if (colCount != that.getColumnCount()) { return false; } for (int r = 0; r < rowCount; r++) { for (int c = 0; c < colCount; c++) { Object v1 = getObject(r, c); Object v2 = that.getObject(r, c); if (v1 == null) { if (v2 != null) { return false; } } else { if (!v1.equals(v2)) { return false; } } } } return true; } KeyedObjects2D(); int getRowCount(); int getColumnCount(); Object getObject(int row, int column); Comparable getRowKey(int row); int getRowIndex(Comparable key); List<Comparable> getRowKeys(); Comparable getColumnKey(int column); int getColumnIndex(Comparable key); List<Comparable> getColumnKeys(); Object getObject(Comparable rowKey, Comparable columnKey); void addObject(Object object, Comparable rowKey,
            Comparable columnKey); void setObject(Object object, Comparable rowKey,
            Comparable columnKey); void removeObject(Comparable rowKey, Comparable columnKey); void removeRow(int rowIndex); void removeRow(Comparable rowKey); void removeColumn(int columnIndex); void removeColumn(Comparable columnKey); void clear(); @Override boolean equals(Object obj); @Override int hashCode(); @Override Object clone();  }### Answer:
@Test public void testEquals() { KeyedObjects2D k1 = new KeyedObjects2D(); KeyedObjects2D k2 = new KeyedObjects2D(); assertEquals(k1, k2); assertEquals(k2, k1); k1.addObject(99, "R1", "C1"); assertFalse(k1.equals(k2)); k2.addObject(99, "R1", "C1"); assertEquals(k1, k2); }