Интерфейс IEqualityComparer в Java

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

boolean Equals(T object1, T object2);

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

int getHashCode(T object);

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

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

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

Ответ 1

Нет встроенного типа, который используется для этого в Java. Это "дыра" в дизайне коллекций, ИМО. Я боюсь, что существует класс Collator, который близок к тому, который он получает.

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

В конце концов я решил написать то, что я делаю в подобных случаях. Если мне нужно специальное равенство/хэш - например, сохраняя слабые ссылки. Вы можете обернуть такой ключ. В целом он не очень отличается от интерфейса, но он создает немые экземпляры (например, 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;
    }
}