Переопределить метод deepEquals() в Java без использования метода Java.util.*

Что-то не так с методом 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;
    }
this == null этот чек бесполезен, this никогда не бывает нулевым. Но зачем вам deepEquals? Просто вызовите equals (или Objects.equals(a, b)) на своих объектах. Ваш метод deep_equals ничего не добавляет к обычному методу equals.
knittl 27.11.2022 11:20

@knittl Спасибо за совет. Я удалю this == null чек. Потому что тест требует, чтобы мы сами переопределяли метод equals, но то, что я написал, не может пройти тест deepEqual. Если метод equal, написанный мной, может пройти тест deepEqual, можно не иметь deepEquals отдельно.

zixuan zhu 27.11.2022 12:05

Здесь я сначала пытаюсь сравнить объект o и this, а также элементы в каждом объекте по одному. Если один из элементов в этих двух объектах является ArrayDeque или LinkedListDeque или чем-то подобным, я думаю, мне нужно сначала вызвать deepEquals, чтобы запустить цикл в самом этом элементе (вызов equals). Я думаю, что оба метода должны быть переопределены? Я не уверен. @user16320675

zixuan zhu 27.11.2022 12:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам понадобится, чтобы ваш метод 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? Извините, я не ясно выразился в заголовке.

zixuan zhu 27.11.2022 12:19

@zixuanzhu взгляните на реализацию и реализуйте ее сами. По сути, он выполняет нулевую проверку на равенство.

knittl 27.11.2022 12:28

Другие вопросы по теме