Что-то не так с методом deepEquals в моем файле ArrayDeque, но я не могу понять.
Это также должно иметь смысл для LinkedListArrayDeque.
Как заставить работать deepEquals без использования Java.util.* method?
Приведенный ниже код относится к двусторонней очереди массива, где первый элемент был добавлен в середину массива. Я удалил несколько методов для краткого просмотра.
package deque;
import java.util.Iterator;
public class ArrayDeque<T> implements Deque<T>, Iterable<T> {
private T[] ts;
private int size;
private int stposition;
private int firposition;
private int lastposition;
public ArrayDeque() {
ts = (T[]) new Object[8];
size = 0;
stposition = Math.round(ts.length / 2);
firposition = stposition;
lastposition = stposition;
}
public T get(int i) {
if (size < i | size == 0) {
return null;
}
int pos = (firposition + i) % ts.length;
return ts[pos];
}
public int size() {
return size;
}
@Override
public Iterator<T> iterator() {
return new ArrayDequeIterator();
}
private class ArrayDequeIterator implements Iterator<T> {
private int pos0 = firposition;
public boolean hasNext() {
if (size == 0) {
return false;
}
if (pos0 == lastposition) {
return true;
}
if (size > 1) {
if (firposition < lastposition) {
if (pos0 < lastposition) {
return true;
}
} else {
if (pos0 + 1 < ts.length) {
return true;
}
}
return false;
}
return false;
}
public T next() {
T x = ts[pos0];
pos0 = (pos0 + 1) % ts.length;
return x;
}
}
@Override
public boolean equals(Object o) { // the equal method passed the tests but deepequal fail
if (o == this) {
return true;
}
if (o == null || this == null) {
return false;
}
if (!(o instanceof Deque)) {
return false;
}
Deque oll = (Deque) o;
if (oll.size() != this.size()) {
return false;
}
for (int i = 0; i < this.size(); i++) {
Object a2 = oll.get(i);
Object a1 = this.get(i);
if (a1 == a2) {
continue;
}
if (a2 == null) {
return false;
}
if (a1.getClass() != a2.getClass()) {
return false;
}
return deepEquals(a1, a2);
}
return true;
}
private boolean deepEquals(Object a1, Object a2) {
boolean deq;
if (a1 instanceof Deque) {
// maybe it's wrong here, I am not sure how to write this
deq = a1.equals(a2);
} else {
if (a1 == a2) {
return true;
}
return false;
}
return deq;
}
}
Я наконец-то понял. Спасибо за помощь.
Это действительно не нуждается в другом deepEqual методе.
Достаточно самого метода equals.
Код выглядит следующим образом:
(1. В моем интерфейсе iterator нет метода deque, поэтому я просто использовал метод get(i). Но я могу использовать его для this. Спасибо за совет от @knittl.
2. Я думаю, что (!a1.equals(a2)) важен в моем коде.. Наконец-то я понял это!...).
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null) {
return false;
}
if (!(o instanceof Deque)) {
return false;
}
Deque oll = (Deque) o;
if (oll.size() != this.size()) {
return false;
}
int i = 0;
for (final Object a1 : this) {
Object a2 = oll.get(i);
i += 1;
if (a1 == a2) {
continue;
}
if (a2 == null) {
return false;
}
if (a1.getClass() != a2.getClass()) {
return false;
}
if (!a1.equals(a2)) {
return false;
}
}
return true;
}
@knittl Спасибо за совет. Я удалю this == null чек. Потому что тест требует, чтобы мы сами переопределяли метод equals, но то, что я написал, не может пройти тест deepEqual. Если метод equal, написанный мной, может пройти тест deepEqual, можно не иметь deepEquals отдельно.
Здесь я сначала пытаюсь сравнить объект o и this, а также элементы в каждом объекте по одному. Если один из элементов в этих двух объектах является ArrayDeque или LinkedListDeque или чем-то подобным, я думаю, мне нужно сначала вызвать deepEquals, чтобы запустить цикл в самом этом элементе (вызов equals). Я думаю, что оба метода должны быть переопределены? Я не уверен. @user16320675




Вам понадобится, чтобы ваш метод equals сравнивал каждый элемент в списке на равенство. Если два элемента не равны, вернуть false. Обратите внимание, что доступ к элементу в связанном списке по индексу — это O(n), что означает, что ваш метод equals имеет квадратичную сложность времени выполнения. Используйте итераторы, чтобы избежать этого.
// ...
for (int i = 0; i < this.size(); i++) {
Object a2 = oll.get(i);
Object a1 = this.get(i);
if (!Objects.equals(a1, a2)) {
return false;
}
}
return true;
}
С итераторами (что дает вам линейную сложность времени выполнения):
// ...
Iterator<Object> otherIterator = oll.iterator();
for (final Object a1 : this) {
// guaranteed to work, because both lists have the same size:
final Object a2 = otherIterator.next();
if (!Objects.equals(a1, a2)) {
return false;
}
}
return true;
}
Нам не разрешено использовать встроенную в Java структуру данных LinkedList (или любую структуру данных из java.util.*) в нашей реализации. Как я могу реализовать Objects.equals(a1, a2) на Java? Извините, я не ясно выразился в заголовке.
@zixuanzhu взгляните на реализацию и реализуйте ее сами. По сути, он выполняет нулевую проверку на равенство.
this == nullэтот чек бесполезен,thisникогда не бывает нулевым. Но зачем вамdeepEquals? Просто вызовитеequals(илиObjects.equals(a, b)) на своих объектах. Ваш метод deep_equals ничего не добавляет к обычному методуequals.