Как бороться с рекурсивными хэш-кодами [duplicate]

Функция разделения строк может принимать опцию логического аргумента «expand».

Вот решение, использующее этот аргумент:

a.var1.str.split(",",expand=True).set_index(a.var2).stack().reset_index(level=1, drop=True).reset_index().rename(columns={0:"var1"})
31
задан Tom 14 January 2012 в 17:52
поделиться

5 ответов

Я согласен с комментарием I82. То, что вам следует избегать ссылки B на родителя: это дублирование информации, которое обычно приводит только к неприятностям, но вам может понадобиться сделать это в вашем случае.

если вы оставите родительскую ссылку в B, в отношении хэш-кодов вы должны полностью игнорировать родительскую ссылку и использовать внутренние переменные true B для построения хеш-кода.

A s - это только контейнеры, и их значение полностью определяется их содержимым, которое является значениями содержащихся B s, и поэтому должны иметь свои хэш-ключи.

Если A является неупорядоченным множеством, вы должны быть очень осторожны, чтобы хэш-код, который вы строили из значений B (или [х7 хэш-коды]), не зависит от какого-либо заказа. Например, если хэш-код создается путем добавления и умножения хеш-кодов содержащихся B в некоторой последовательности, вы должны сначала заказать хеш-коды, увеличив порядок перед вычислением результата сумм / умножений. Аналогично, A.equals(o) не должен зависеть от порядка B s (если неупорядоченный набор).

Обратите внимание, что если вы используете java.util.Collection внутри A, просто установите B s, игнорируя родительскую ссылку, автоматически выдаст действительные хеш-коды A, поскольку по умолчанию Collection имеют хорошие хеш-коды (упорядочение или нет).

5
ответ дан toto2 1 September 2018 в 10:48
поделиться

Прежде всего, вы уверены, что хотите переопределить Equals() и GetHashCode()? В большинстве сценариев вы должны быть в порядке с ссылочным равенством по умолчанию.

Но, допустим, нет. Чем, какова соответствующая семантика равенства, которую вы хотите?

Например, предположим, что каждый A имеет поле getB типа B, и каждый B имеет поле getA типа A. Пусть a1 и a2 - два объекта A, имеют одинаковые поля и одинаковые getB (такие же, как в «том же адресе памяти») b1. Являются ли a1 и a2 равными? Предположим, что b1.getA совпадает с a1 (то же, что и в «том же адресе памяти»), но не совпадает с a2. Вы все еще хотите считать a1 и a2 равными?

Если нет, не переопределяйте что-либо и не используйте ссылочное равенство по умолчанию.

Если да, то вот решение: пусть A имеет функцию int GetCoreHashCode(), которая не зависит от элемента getB (но зависит от других полей). Пусть функция B имеет функцию int GetCoreHashCode(), которая не зависит от элемента getA (но зависит от других полей). Пусть теперь функция int GetHashCode() A зависит от this.GetCoreHashCode() и getB.GetCoreHashCode(), а также для B, и вы закончили.

-2
ответ дан Ali Ferhat 1 September 2018 в 10:48
поделиться

В типичной модели большинство объектов имеют уникальный идентификатор. Этот идентификатор полезен в различных случаях использования (в частности: восстановление базы данных / поиск). IIUC, поле bKey должно быть таким уникальным идентификатором. Таким образом, общая практика сравнения таких объектов заключается в сравнении их идентификаторов:

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (!getClass().equals(obj.getClass()))
        return false;
    return this.bKey.equals(((B) obj).bKey);
}


@Override
public int hashCode() { return bKey.hashCode(); }

Вы можете спросить: «что произойдет, если два объекта B имеют одинаковый идентификатор, но другое состояние (значение их полей отличается )». Ваш код должен убедиться, что таких вещей не происходит. Это будет проблемой, независимо от того, как вы реализуете equals() или hashCode(), потому что это по существу означает, что у вас есть две разные версии одного и того же объекта в вашей системе, и вы не сможете определить, что является правильным.

3
ответ дан Itay Maman 1 September 2018 в 10:48
поделиться
1
ответ дан jhegedus 1 September 2018 в 10:48
поделиться

У вас может быть два варианта equals - переопределение Object.equals и одно, которое лучше подходит для рекурсии. Рекурсивная проверка равенства принимает A или B - в зависимости от того, какой класс другого этого объекта - это объект, который вы называете рекурсивным равенством от имени. Если вы вызываете его от имени this.equals, вы проходите в null. Например:

A {
    ...
    @Override
    public boolean equals(Object obj) {
        // check for this, null, instanceof...
        A other = (A) obj;
        return recursiveEquality(other, null);
    }

    // package-private, optionally-recursive equality
    boolean recursiveEquality(A other, B onBehalfOf) {
        if (onBehalfOf != null) {
            assert b != onBehalfOf;
            // we got here from within a B.equals(..) call, so we just need
            // to check that our B is the same as the one that called us.
        }
        // At this point, we got called from A.equals(Object). So,
        // need to recurse.
        else if (b == null) {
            if (other.b != null)
                return false;
        }
        // B has a similar structure. Call its recursive-aware equality,
        // passing in this for the onBehalfOf
        else if (!b.recursiveEquality(other.b, this))
            return false;

        // check bkey and return
    }
}

Итак, после A.equals:

  1. A.equals вызывает `recursiveEquality (otherA, null), если this.b != null, мы закончили третий блок if-else, который вызывает b.recursiveEquality(other.b, this) в B.recursiveEquality, мы попали в блок first if-else, который просто утверждает, что наш A является тем же, который был передан нам (т. е. что круговая ссылка не нарушена), мы заканчиваем B.recursiveEquality, проверяя aKey (в зависимости от ваших инвариантов вы можете утверждать что-то, основанное на том, что произошло на шаге 3). B.recursiveEquality возвращает A.recursiveEquality, проверяя bKey, возможно, с аналогичными утверждениями
  2. A.equals возвращает результат проверки рекурсивного равенства
0
ответ дан yshavit 1 September 2018 в 10:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: