Интерфейс 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;
}
}