2011-01-29 14 views
11

Más específicamente, quiero una interfaz para comparar objetos que solo se pueden comparar por igualdad [p. Ej. números complejos] pero no tienen un orden total en ellos. Debe tener [Nota que sólo devuelve un boolean sí/no]Interfaz IEqualityComparer en Java

boolean Equals(T object1, T object2); 

y una función de código hash. De modo que cuando los distribuyo en cubos utilizando objetos para recoger objetos "iguales", 2 objetos "iguales" no terminan en dos cubos diferentes.

int getHashCode(T object); 

¿Java tiene uno? Busqué y no pude encontrarlo.

estoy tratando de utilizar esto en Hadoop MapReduce para distribuir objetos "iguales" a reducir mismo trabajo para que pueda operar en todos los objetos "iguales". Solo me importa si los objetos son iguales o no y no necesito un orden total. Pero si dos objetos son iguales, deberían tener el mismo código hash. De lo contrario, terminarán en dos trabajos de reducción diferentes.

Tenga en cuenta que lo que sé de los iguales y código hash del objeto. Pero quiero un comparador externo que, digamos, depende de solo una parte de un objeto. Entonces, la noción de igualdad de objeto difiere de la mía.

+0

No tengo idea acerca de la analogía de C#, pero ¿has verificado la clase 'Object'? Tiene los métodos 'equals()' y 'hashCode()'. Básicamente es heredado (y anulable) en todas las clases. http://download.oracle.com/javase/6/docs/api/java/lang/Object.html ¿O tal vez necesitas el 'Comparador'? http://download.oracle.com/javase/6/docs/api/java/util/Comparator.html – BalusC

+4

No, quiero un comparador externo. Tengo una noción diferente de "igualdad" de la igualdad de los objetos mismos.Supongamos que quiero comparar solo una parte del objeto, pero el objeto itslef implementa la igualdad en todos los campos. – Fakrudeen

+0

java.util estándar no es compatible con una funcionalidad similar. – bestsss

Respuesta

10

hay ningún tipo incorporado que se utiliza para esto en Java. Es un "agujero" en el diseño de colecciones, IMO. Existe la clase específica de cadena Collator que es lo más cerca posible, me temo.

No hay manera de personalizar los mapas incorporados a utilizar un tipo específico de comparación de igualdad, peor suerte. Es completamente razonable querer esta funcionalidad, y un dolor real que no está presente todavía.

Usted puede crear su propia interfaz de este tipo, por supuesto, y escribir sus propias variantes mapa que lo utilizan ... pero tener que hacerlo chupa :(

+0

Sí, terminé definiendo mi propio EqualityComparator , que es una copia exacta de IEqualityComparer , ya que solo necesito este contrato entre mi componente map-reduce y los usuarios. Para alguien que intente usar HashSet, etc., será muy doloroso. – Fakrudeen

+0

IIRC, hay algunas implementaciones, Google para "Equalator". – maaartinus

2

se recomienda usar un enfoque basado en la función de generar los cubos como el MultiMaps.index() method in Google collections (ahora guayaba) hace. utilizan un Function<V,K> que mapea los objetos de tipo V a las teclas de tipo K (en su caso, los cubos).

+2

Curiosamente, Guava define la [Equivalencia ] (http://guava-libraries.googlecode.com/svn/tags/release08/javadoc/com/google/common/base/class-use/Equivalence.html) interfaz para esto , pero no lo usa en ninguna de sus implementaciones de Mapas. – finnw

+1

@finnw - Eso es exactamente lo que quiero. Pero no quiero usar esa biblioteca solo para esa interfaz. Pero es bueno saberlo. Lo usaré la próxima vez, cuando ya tenga una dependencia de él. – Fakrudeen

0

al final he optado por escribir lo que hago en casos similares. Si necesito igualdad/hash especial, como por ejemplo mantener las referencias débiles. Puede ajustar la clave de esa manera. En general, no es ver y diferente del enfoque de interfaz, pero crea instancias tontas (como HashMap/Hashtable para las entradas de cubo). Puede que sea necesario desenvolver extra por conjunto de claves() y así sucesivamente ...

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; 
    } 
} 
7

El tipo que desea es Guayaba de Equivalence. Sin embargo, puede ser decepcionado, como en Java y CollectionMap son bastante rígidamente especificado en términos de Object.equals, y que no encontrará en las implementaciones de los de guayaba que utilizan una equivalencia alternativo. Sin embargo, puede simular ese comportamiento un poco usando myEquivalence.wrap(myObject).

Cuestiones relacionadas