2010-09-27 11 views
7

Esta es una pregunta de programación trivial. No soy un experto en Java. Digamos que yo utilizo objetos de clases personalizadas de la empresa y de los empleados, de manera similar a lo que muchos RDBMS ejemplos hacen:¿Se puede controlar la identidad de los objetos en Java y, de ser así, cómo?

class Employee 
{ 
    Company company; 
} 

class Company 
{ 
    String name; 
} 

necesito para garantizar que los diferentes Company objetos tienen nombres únicos - es decir, no hay dos de estos objetos pueden tener el mismo nombre, porque desde mi punto de vista no tiene sentido, y también simplemente come memoria: si dos empleados trabajan en IBM, entonces hay un solo objeto Company con ese name, punto.

Lo que pienso ahora es hacer que el constructor Company sea privado, de modo que la tarea de asignar objetos Company con nombres arbitrarios se delegue en un método confiable que suponga que rechazará cualquier intento posterior de crear un objeto con un nombre que ya existe o devuelve un objeto existente o nuevo (creando uno si es necesario).

El problema es que no estoy seguro de cómo lograr esto con elegancia. Una cosa que estaría bien es no tener que hacer una búsqueda O(n) cada vez que se solicita un objeto Company con un nombre, entonces ¿tal vez un mapa hash o un árbol binario está ahí para mi conveniencia? También me gustaría anular la forma en que se identifican los objetos Company, lo que me lleva a esto: ¿voy a anular los métodos Object.equals y/o Object.hashCode?

+0

¿Está seguro de que debería preocuparse por el uso de memoria adicional? Tendrás que pagar por mantener un registro de todas las compañías de alguna manera, y te costará (probablemente en la CPU). Asegúrese de que su optimización no sea prematura. – nojo

+0

Esto no es necesariamente tanto para la optimización, ya que es por la importancia de la restricción que deben evitarse dos objetos 'Company' con el mismo nombre. De esa forma, si, digamos que la compañía a la que hacen referencia los N empleados cambia de nombre, solo tengo que hacerlo para un objeto 'Empresa'. Cosas como esas. – amn

Respuesta

4

Puede anular equals y hashCode y almacenarlos en un HashMap o HashSet.

+0

¿cómo los buscarías? –

+0

@Michael: vea el patrón de peso mosca mencionado a continuación. – aperkins

+0

@Michael Mi idea básica era que permitiría todo tipo de usos que podrían ser naturales, como 'map.get (company)' o 'set.contains (company)'. –

8

Eche un vistazo al patrón de peso mosca.

Lo que me gustaría hacer es algo como:

// incomplete, but you get the idea hopefully 
CompanyFactory 
{ 
    private Map<String, Company> companies; 

    public getCompany(final String name) 
    { 
     Company company; 

     company = compaines.get(name); 

     if(company == null) 
     { 
      company = new Company(name); 
      companies.put(name, company); 
     } 

     return (company); 
    } 
} 
+0

+1 - Este es el problema exacto que el patrón de peso mosca fue diseñado para resolver. :) – aperkins

+0

Sí, eso es lo que comencé a hacer. Sin embargo, me preocupan las referencias a los objetos de la empresa: parece que este mapa, aunque útil aquí, conservará las referencias a todos los objetos de la empresa que se hayan creado, aunque no quede más referencias "buenas" para estos objetos. Estoy pensando en un WeakHashMap, pero el débil se refiere a las claves, no a los valores: '- ( – amn

+0

Creo que cuando se quita la clave de WeakHashMap, el valor también se elimina, y por lo tanto es elegible para la recolección de basura. – TofuBeer

1

Una cosa que sería bueno no es tener que hacer un O (n) las operaciones de búsqueda cada vez que un objeto de empresa con un nombre es solicitado - entonces tal vez un mapa hash o un árbol binario está ahí para mi conveniencia?

Eso suena bien, sí.

También me gustaría para invalidar la forma de identificar los objetos de la compañía - que me lleva a esto: voy a ser preponderantes Object.equals y/o métodos Object.hashCode?

Si se asegura de que nunca hay dos casos con el mismo valor de clave, que en realidad no hacer tienen que hacer eso.

1

Cuando quiero crear una colección de objetos que pueden ser buscados por nombres únicos, almaceno un Map de cadenas (nombres) en Objetos. Luego puedo buscar el objeto relacionado con un nombre.

Estrictamente hablando, no necesita tocar equals() y hashCode() para hacer eso, ya que no está almacenando sus objetos como llaves.Implementar equals() y hashCode() correctamente puede ser difícil de obtener, y las claves en una implementación de Map como HashMap (que puede proporcionarle búsquedas eficientes) son sensibles a estos métodos. Usar la clase existente (y crucialmente inmutable) String como claves lo ayuda a obtener esta funcionalidad de búsqueda correcta.


Actualización: Si hace que su constructor sea privado, como mencionó, puede evitar la creación de nuevas instancias de empresa. Proporcionar algún otro método para crear instancias de empresa (Factory pattern) le permite asegurarse de que las instancias de empresa 'nuevas' sean realmente nuevas si aún no están almacenadas por nombre; de ​​lo contrario, se devuelve la instancia existente para un nombre dado (ejemplo Singleton)

+0

En realidad, almacenar una cadena como la clave no es matemáticamente suficiente. Es matemáticamente posible que 2 cadenas diferentes hagan hash con el mismo valor. –

+5

... que los coloca en el mismo cubo, y el método String equals() se encarga de garantizar la singularidad ...? – Brabster

+0

@John En realidad es suficiente. – EJP

0

Si el nombre de un objeto puede cambiar con el tiempo, considere incluir un ID único generado para cada objeto. Su asignación sería de nombre a ID único, luego de ID único al objeto real.

Por cierto, si todos los objetos eran conocidos en tiempo de compilación, podría usar un Enum.

Cuestiones relacionadas