Перезапись методов hashCode () и equals () в Java - PullRequest
1 голос
/ 25 февраля 2020

Как следует из заголовка, мой вопрос имеет отношение к переопределению методов hashCode () и equals (). Тем не менее, это также не совсем верно, я просто не знал другого способа подвести итог моего вопроса.

У меня есть объект Label, который содержит несколько компонентов, один из которых - List, который содержит несколько объекты типа Node. Примером Label будет: [(n1, n2, n3), (n4, n5)]. Я хочу хранить все уникальные Label объекты, сгенерированные в LinkedHashSet. Тем не менее, это не работает, как ожидалось. Предположим, что LinkedHashSet в настоящее время содержит Label, описанный выше, и что теперь мы сгенерировали новый Label с именем other, который, как оказалось, содержит те же узлы, что и уже добавленная метка, таким образом, также [(n1, n2, n3), (n4, n5)]. Поскольку у него такой же список узлов, остальные компоненты в Label также идентичны. Я не буду объяснять здесь, почему, просто предположите, что это так, потому что это так. Однако при проверке, содержит ли LinkedHashSet уже Label, возвращается false, поскольку объекты имеют разные идентификаторы объектов.

Один из подходов - написать for-l oop вместо LinkedHashSet и сравнить новую метку со всеми метками в LinkedHashSet, но это будет очень дорого с точки зрения времени выполнения, поэтому я ищу более дешевый вариант. Любые предложения приветствуются!

Другой подход заключается в адаптации метода equals(), но это не сработало, поскольку мне также пришлось адаптировать метод hashCode(), и я не знаю, что это изменить чтобы заставить это работать.

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

Вы определенно не хотите "for-l oop сверх LinkedHashSet и сравнивать ..." Обнаружение дубликатов - это то, что LinkedHashSet должен делать. Для этого ему нужны соответствующие реализации equals и hashCode.

. Вы, вероятно, понимаете, что вам нужно реализовать equals таким образом, чтобы он возвращал значение true, когда Label "равен" "другой Label, как бы вы ни определили это. Если две метки равны, когда они имеют одинаковые узлы, то да, вам в значительной степени придется посмотреть на все узлы и убедиться, что они одинаковы.

То есть hashCode. Вы должны реализовать hashCode, чтобы соответствовать equals, то есть, если две метки равны, они должны иметь одинаковый код ha sh. Это потому, что LinkedHashSet собирается использовать код ha sh для определения корзины, в которой находится Label, а затем использовать equals для сравнения новых Label с теми, которые уже существуют в корзине. Если две метки равны, но генерируют разные коды ha sh, LinkedHashSet не сможет обнаружить их как дубликаты.

Самое простое, что можно сделать, это включить коды ha sh все узлы в коде ha sh Label. Что-то вроде:

int hashCode() {
    int hc = 1;
    for (Node n : allMyNodes) {
        hc = hc * 31 + n.hashCode();
    }
    return hc;
}

Если есть много узлов и маловероятно, что две метки будут совместно использовать один и тот же узел, если они не «равны», вы можете просто использовать код ha sh первого узел, а не рыться в них все.

1 голос
/ 25 февраля 2020

Реализация equals (...) и hashCode (...) - правильный подход. Обычно люди используют свои IDE для генерации этих методов для них, вот как это будет выглядеть с Java 7 +:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Label label = (Label) o;
        return Objects.equal(nodes, label.nodes);
    }

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

Если у вас есть несколько полей, это становится:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Label label = (Label) o;
        return Objects.equal(nodes, label.nodes) &&
                Objects.equal(other, label.other);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(nodes, other);
    }

Однако это будет работать, только если реализации для Node также реализуют equals(...) и hashCode(...).

0 голосов
/ 25 февраля 2020

Используйте @EqualsAndHashCode из lombok в вашем Node (или Label) классе.

Затем вы можете добавить узлы к вашему LinkedHashSet.

...