Интерфейс IEqualityComparer в Java - PullRequest
12 голосов
/ 29 января 2011

Точнее, я хочу, чтобы интерфейс сравнивал объекты, которые можно сравнивать только на равенство [например, комплексные числа], но не иметь общего порядка на них.Он должен иметь [Обратите внимание, что он возвращает только логическое да / нет]

boolean Equals(T object1, T object2);

и функцию хэш-кода.Так что, когда я распределяю их по группам, используя объекты, скажем, для сбора «равных» объектов, 2 «равных» объекта не оказываются в двух разных сегментах.

int getHashCode(T object);

Есть ли в Java один?Я искал и не смог его найти.

Я пытаюсь использовать это в Hadoop Map Reduce, чтобы распределить «равные» объекты для одинакового сокращения работы, чтобы я мог работать со всеми «равными» объектами.Меня интересует только, равны ли объекты или нет, и мне не нужен общий порядок.Но если два объекта равны, они должны иметь одинаковый хэш-код.В противном случае они окажутся в двух разных заданиях сокращения.

Обратите внимание, что я знаю о равных и хэш-коде объекта.Но я хочу внешний компаратор, который говорит, что зависит только от части объекта.Так что понятие равенства объекта отличается от моего.

Ответы [ 4 ]

10 голосов
/ 29 января 2011

Нет встроенного типа, который используется для этого в Java.Это «дыра» в дизайне коллекций, IMO.Боюсь, что есть специфичный для строки класс Collator , который настолько близок, насколько это возможно.

Нет способа настроить встроенные карты для использования определенного вида равенствасравнение, хуже удачи. вполне разумно хотеть эту функциональность, и очень жаль, что ее еще нет.

Конечно, вы можете создать свой собственный такой интерфейс и написать свои собственные варианты карт, которые его используют... но то, что нужно сделать - отстой: (* ​​1009 *

7 голосов
/ 31 октября 2014

Тип, который вам нужен - это Guava's Equivalence. Однако вы можете быть разочарованы, поскольку в Java Collection и Map довольно жестко определены в терминах Object.equals, и вы не найдете реализации тех в Guava, которые используют альтернативную эквивалентность. Однако вы можете немного смоделировать это поведение, используя myEquivalence.wrap(myObject).

2 голосов
/ 29 января 2011

Я бы предложил использовать основанный на функциях подход для генерации сегментов, как метод MultiMaps.index () в коллекциях Google (теперь Guava). Они используют Function<V,K>, который отображает объекты типа V на ключи типа K (в вашем случае это сегменты).

0 голосов
/ 29 января 2011

В конце концов я решил написать, что я делаю в подобных случаях. Если мне нужно особое равенство / хэш - как, например, хранение слабых ссылок. Вы можете обернуть ключ, как это. В целом, он не очень отличается от интерфейсного подхода, но создает немые экземпляры (например, HashMap / Hashtable для записей сегмента). Вам может понадобиться дополнительная распаковка для keySet () и т. Д. ...

package t1;

public abstract class KeyX<Key> implements java.io.Serializable {
    private static final long serialVersionUID = 0l;

    final Key key;
    final int hash;
    protected KeyX(Key key){
        this.key = key;
        this.hash = hashCode(key);
    }

    protected abstract int hashCode(Key key);

    //Key, Key will be way too strict and it'd required, key.getClass().isInstance(y) prior calling
    protected abstract boolean equals(Key x, Object y);

    @Override
    public final boolean equals(Object obj) {
        if (obj==this)
            return true;
        if (!(obj instanceof KeyX)){
            return false;
        }
        final KeyX<?> other = (KeyX<?>) obj;
        return this.key==other.key ||  (hash==other.hash && other.key!=null  && equals(this.key, other.key)); 

    }

    @Override
    public final int hashCode() {
        return hash;
    }

    public final Key unwrap(){
        return key;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...