2012-06-03 15 views
8

He leído acerca de LinkedHashMap y de la descripción (aunque muy interesante) no pude entender cómo hace su trabajo bajo el capó. Como nota al margen, sé cómo funciona un HashMap debajo en Java.
Así que reviso la fuente y todavía no puedo entender cómo funciona. Tal vez no estoy captando algo fundamental en OOP en este caso tan desnudo conmigo.
Para resumir la parte que me resulta confusa es la siguiente:
El LinkedHashMap delega todas las llamadas a su principal HashMap.
Internamente se anula la HashMap.Entry para poner en práctica las diversas recordAccess y recordRemoval métodos que parecen poner en práctica la lógica de la LinkedHashMap
Pero el actual Entries se encuentran dentro de la tabla de la clase base es decir, el HashMap la que crea la instancia de una tabla de HashMap.Entry y no de LinkedHashMap.Entry.
Así que no puedo entender cómo se llaman realmente los diversos recordAccess y recordRemove, etc.
Entonces, ¿alguien puede ayudarme a entender qué está pasando aquí?
¿Tengo razón al pensar que de alguna manera el LinkedHashedMap.Entry es el tipo de tabla creada por el HashMap? ¿Pero cómo?De vuelta en los fundamentos de OO. ¿Cómo funciona LinkedHashMap bajo el capó? No puedo entender esto

ACTUALIZACIÓN:
Mi pregunta es ¿cómo la recordAccess están siendo llamados. Mi experimento en esta usando una versión derivada de HashMap no por la razón de Shengyuan Lu (1) - Mi mal no

ACTUALIZACIÓN:
Lo siguiente que probé es el mismo (creo) como lo que el LinkedHashMap está haciendo:

package delete; 

public class Base<T> { 

    Entry<T>[] table; 
    int idx = 0; 
    @SuppressWarnings("unchecked") 
    public Base(){ 
     System.out.println("In base"); 
     table = new Entry[10]; 
    } 

    public void add(T x){ 
     table[idx] = new Entry(x); 
     table[idx].doSomething(); 
    } 

    static class Entry<T>{ 
     T value; 

     Entry(T x){ 
      this.value = x; 
      System.out.println("Entry::Base"); 
     } 

     void doSomething(){ 
      System.out.println("In Entry base, doing something"); 
     } 
    } 

} 




public class Derived<T> extends Base<T> { 

    static class Entry<T> extends Base.Entry<T>{ 

     Entry(T x) { 
      super(x); 
      System.out.println("In Entry derived"); 
     } 

     int val; 

     @Override 
     void doSomething() { 
      System.out.println("In Entry derived doing something really smart!"); 
     }  
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 

     Base<String> b = new Derived<String>(); 
     b.add("Test string"); 

    } 

} 

pero se imprime:

In base 
Entry::Base  
In Entry base, doing something  

Así que la derivada es Entry nev er llamado.
¿Es mi ejemplo diferente de alguna manera? No puedo entender cómo esto funciona para LinkedHashMap

+0

¿Protegido o paquete privado? – assylias

+0

@assylias: OP – Cratylus

+2

actualizado para _¿Por qué LinkedHashMap se define como extiende HashMap implementa Map_ read [this] (http://stackoverflow.com/q/2165204/1393766) – Pshemo

Respuesta

3

Si define MyLinkedHashMap bajo el paquete de java.util, se compilará;)

Porque es HashMap.HashEntry visibilidad de paquete.

PLUS:

Creo que lo más importante es que desconcertado LinkedHashMap.Entry vs HashMap.Entry. El punto es LinkedHashMap.Entry is-a HashMap.Entry. En realidad, HashMap.table almacena LinkedHashMap.Entry en LinkedHashMap.

Con respecto a recordAccess y recordRemoval, ambos anulan las versiones de HashMap.Entry. Puede encontrar las referencias tanto en LinkedHashMap como en HashMap.

Fusionar comentarios aquí: El código de muestra no es el mismo que LinkedHashMap implementación. Ver LinkedHashMap.addEntry() en su lugar.

+0

¿Pero cómo? 'HashMap' hace' table = new Entry [DEFAULT_INITIAL_CAPACITY]; '. – Cratylus

+0

@ user384706 Piensa en 'Object [] table = new Object [1]; table [0] = "Soy una subclase de Object"; ' –

+0

Consulte la actualización en OP – Cratylus

2

Ctrl + F es su amigo aquí, especialmente cuando le permite buscar varios archivos a la vez. recordAccess se invoca en la entrada accedida/creada por los métodos put y get del mapa. (Las llamadas están en HashMap.put, HashMap.putForNullKey y LinkedHashMap.get). Solo es relevante si utiliza el constructor de LinkedHashMap que toma un parámetro booleano y lo pasa a true. El efecto de esto es que cada vez que toca el mapa, la entrada tocada se moverá al frente de la lista vinculada interna.

Citando la documentación:

Se proporciona un constructor especial para crear un mapa hash ligado cuyo orden de iteración es el orden en que se accedió por última sus entradas, de menos recientemente visitada con más recientemente (orden de acceso). Este tipo de mapa es adecuado para construir memorias caché LRU. Invocar el método put u get da como resultado un acceso a la entrada correspondiente (suponiendo que existe después de que se complete la invocación). El método putAll genera un acceso de entrada para cada asignación en el mapa especificado, en el orden en que las asignaciones de clave-valor son proporcionadas por el iterador del conjunto de entrada del mapa especificado. Ningún otro método genera accesos de entrada. En particular, las operaciones en vistas de colección no afectan el orden de iteración del mapa de respaldo.

El método removeEldestEntry (Map.Entry) se puede reemplazar para imponer una política para eliminar automáticamente las asignaciones caducas cuando se agregan nuevas asignaciones al mapa.

Del mismo modo recordRemoval se llama desde HashMap.removeEntryForKey y HashMap.removeMapping.

Cuestiones relacionadas