JDK1.8.0_144 Dirección de descarga: //www.vevb.com/softs/551512.html
La clase abstracta de AbstractMap implementa algunos métodos simples y generales, que no son difíciles en sí mismo. Pero hay dos métodos en esta clase abstracta a los que vale la pena prestar atención. Se puede decir que la implementación del código fuente del método KeySet y valores son modelos de estilo de texto.
Las clases abstractas generalmente se implementan como un esqueleto para implementar métodos comunes para sus respectivas subclases. En el artículo anterior, explicamos la interfaz del mapa, y este artículo analiza y estudia la clase de resumen abstractsmap.
Hay muchas estructuras de datos de tipo de mapa en Java. AbstractMap, como su implementación de esqueleto, implementa algunos métodos de la interfaz de mapa, es decir, proporciona métodos públicos para sus subclases, y varios mapas sin implementación pueden ser diferentes.
Una clase abstracta no puede crear directamente instancias de clases abstractas a través de la nueva palabra clave, pero puede tener constructores. AbstractMap proporciona un constructor sin parámetros modificado protegido, lo que significa que solo su subclase puede acceder (por supuesto, es una clase abstracta en sí, y otras clases no pueden ser instanciadas directamente), es decir, solo su subclase puede llamar a este constructor sin parámetros.
Una interfaz de entrada se define internamente en la interfaz del mapa. Esta interfaz es una implementación interna del mapa del mapa para mantener un par de clave de valor clave, y el valor clave se almacena en este map.entry. AbstractMap implementa esta interfaz interna, hay dos en total: uno es la simple centry mutable y la otra es la inmutable SimpleMutableEntry.
Public static class SimpleEntry <K, V> Implementa la entrada <k, v>, java.io.serializable
Se implementa la interfaz MAP.Entry <K, V> y es serializable (se puede serializar).
Su método es relativamente simple, todos los cuales son operaciones para tomar valores y almacenar valores. La definición de valor clave es una modificación final, lo que significa que es una referencia inmutable. Además, su método SetValue es ligeramente especial. El valor almacenado no es el valor almacenado, pero el valor anterior regresó. Lo que necesita aprender son los métodos iguales y de hashcode que reescribe.
Public boolean iguales (objeto o) {if (! (o instancia de map.entry) // para determinar si los parámetros son de tipo map.entry, si es igual, lo primero que debe hacer es ser el mismo tipo return False; Map.Entry <?,?> E = (map.entry <?,?>) O; // Forzando el tipo de objeto al tipo MAP.Entry, el parámetro usa "?" En lugar de "K, V" porque el tipo de genérico se borrará en tiempo de ejecución. El compilador no sabe qué tipo K y V es, devuelve eq (key, e.getKey ()) && eq (valor, e.getValue ()); // Llama de clave y valor al método EQ para el juicio respectivamente, y es igual a igual cuando ambos devuelven ture. } EQ booleano estático privado (objeto o1, objeto o2) {return o1 == null? o2 == nulo: o1.equals (o2); // Este operador de tres ítems también es muy simple, pero debe tenerse en cuenta que, aunque O1 y O2 son tipos de objetos aquí, el método igual de tipo de objeto se hace referencia a "==", por lo que no cree que aquí hay un problema, porque en realidad, el tipo O1 puede ser cadena, aunque se convierte en objeto, por lo que el método de##de cadena aún se está llamando cuando llaman el método de ecuaciones. }Para reescribir correctamente el método igual y usarse correctamente, generalmente necesita reescribir el método hashcode.
public int hashcode () {return (key == null? 0: key.hashcode ()) ^ (value == null? 0: value.hashcode ()); // Cuando los valores de clave y valor no son nulos, el húsico se xoreará. }clase pública estática SimpleMutableEntry <k, v> Entrada de implementos <k, v>, java.io.serializable simpliMmutableEntry
La entrada definida como inmutable es realmente inmutable porque no proporciona el método SetValue, y naturalmente no se puede modificar a través del método SetValue cuando se accede a múltiples hilos simultáneamente. En comparación con SimpleEntry, sus variables clave y miembro de valor se definen como tipos finales. Llamar al método SetValue organizará una excepción de Operación de Operación sin apoyo.
Sus iguales y los métodos de hashcode son consistentes con SimpleEntry.
A continuación, verifique qué métodos de la interfaz de mapa son implementados por la clase Abstract de resumen.
Public int size ()
Se define un método de entrada en el mapa, que devuelve la colección establecida de map.entry. El método de tamaño de la colección de conjuntos se llama directamente, que es el tamaño del mapa.
Public Boolean isEmpty ()
Llame al método de tamaño anterior, igual a 0, está vacío.
Public Boolean contiene key (clave de objeto)
La implementación de este método es relativamente simple. Al llamar al método EntrySet, el iterador de la colección establecida se obtiene y atraviesa con la tecla de parámetro. El mapa se puede almacenar como el valor clave de NULL. Dado que Key = NULL se almacena en MAP con almacenamiento especial especial (el valor de hashcode no se puede calcular), también hemos hecho una forma de determinar si la tecla de parámetro está vacía.
Public Boolean ContinsValue (valor de objeto)
Esta implementación del método es consistente con ContinsKey.
Public v Get (clave de objeto)
Esta implementación del método es similar a las dos anteriores, la diferencia es que lo anterior es igual al booleano y este método devuelve el valor.
Public V Put (K Key, V valor)
El método de almacenar pares de valor clave en el mapa no se implementa en detalle, y se lanzará directamente una Operación no compatible.
Public V Retem (clave de objeto)
Elimine el par de valores de valor clave especificado en el mapa a través de la tecla de parámetro. Este método también es muy simple. También atraviesa la colección establecida de map.entry a través de un iterador, encuentra el valor de la clave correspondiente y elimina el map.entry llamando al método de eliminación iterador#.
Public void putall (map <? extiende k, "extiende v> m)
Este método también es muy simple de atravesar el mapa entrante y simplemente llame al método PUT para guardarlo.
Public Void Clear ()
Llame al método EntrySet para obtener la colección establecida y luego llame al método establecer#claro () para borrarlo.
Conjunto público <K> KeySet ()
Devuelve la colección establecida de valores de clave de mapa. AbstractMap define una variable miembro "Conjunto transitorio <k> KeySet". En JDK7, la variable KeySet es modificada por volátil, pero en JDK8, no se modifica por volátil. Se explica en los comentarios sobre la variable KeySet que el método para acceder a estos campos no está sincronizado por sí mismo, y volátil no puede garantizar la seguridad de los subprocesos. La implementación del método KeySet es interesante.
En primer lugar, piense en este método es devolver el conjunto de valores de clave. Naturalmente, podemos pensar en un método de implementación simple, atravesar la matriz de entrada y eliminar el valor clave y ponerlo en el conjunto establecido, similar al siguiente código:
set public <k> keySet () {set <k> ks = null; para (map.entry <k, v> entrada: entrySet ()) {ks.Add (entry.getKey ()); } return ks;}Esto significa que cada vez que se llama al método KeySet, atravesará la matriz de entrada, y la eficiencia se reducirá considerablemente cuando el volumen de datos sea grande. Tengo que decir que el código fuente de JDK está muy bien escrito, y no adopta el método de recorrido. Si no atraviesa la entrada, ¿cómo sabe que ese mapa ha agregado un par de valores de valor clave en este momento?
La respuesta es volver a implementar una nueva colección de conjuntos personalizados dentro del método KeySet, y el método Iterator se reescribe en esta colección de conjuntos personalizados. Aquí está la clave. El método Iterator devuelve la interfaz Iterator, y aquí se vuelve a implementar. Llamando al método EntrySet y luego llamando a su método de iterador. Lo siguiente se analiza en combinación con el código:
Public set <K> keySet () {set <K> ks = keySet; //Defined transient Set<K> keySet if (ks == null) { //The first call is definitely null, create a Set example through the following code ks = new AbstractSet<K>() { //Create a custom Set public Iterator<K> iterator() { //Rewrite the iterator method of the Set collection return new Iterator<K>() { //Reimplement the Iterator interface private Iterador <Entry <k, v >> i = EntrySet (). Iterator (); // Crear un iterador de colección establecido iterador público boolean Hasnext () {return i.hasnext (); // El juicio del valor clave es el juicio de entrada} public k Next () {return I.Next (). GetKey (); // El siguiente valor clave es tomar la entrada#getKey} public void remove () {i.remove (); // Eliminar el valor clave, eliminar la entrada}}; } public int size () {// El método rewritten set#size devuelve abstractMap.this.size (); // El valor de la clave es qué tan grande es el mapa completo, así que simplemente llame al método de tamaño de esta clase. Esta es una clase interna. Use esta palabra clave para representar esta clase directamente. Debe indicar que se llama el método de tamaño en AbstractMap. Sin esto, significa que es un método estático estático} public boolean isEtimty () {// El conjunto rewritten#isEtimty Method devuelve abstractMap.This.IsEmpty (); // Para si hay un valor clave, significa si el mapa está vacío, por lo que es solo llamar al método isEtimty de esta clase} public void clear () {// El conjunto rewritten#Clear Method AbstractMap.THIS.CLEAR (); // Borrar el valor de clave, es solo para borrar el mapa, por lo que es solo llamar al método claro de esta clase} public boolean contiene (objeto k) {// reescribir#contiene método return abstractMap.this.containskey (k); // juzga si el set contiene datos k, lo que significa si el mapa contiene valor clave, por lo que simplemente llame al método contenidos de esta clase}}; keySet = ks; // Asigna esta colección de conjuntos personalizados a la variable KeySet. Al volver a llamar al método KeySet nuevamente en el futuro, debido a que el KeySet no es nulo, solo necesita regresar directamente. } return ks;Creo que esta es una implementación muy inteligente. Aunque este método gira en torno al valor clave, en realidad se puede implementar en combinación con la entrada sin atravesar la entrada. Al mismo tiempo, se menciona anteriormente que llamar al método iterador# de EntrySet, que es la mejor práctica del modo de método de plantilla. Debido a que EntrySet no se implementa en AbstractMap, pero se deja a su subclase para completar, pero el método KeySet se puede implementar con un "esqueleto de algoritmo", que es el patrón de método de plantilla.
Colección pública <v> valores ()
Para el método de valores, puede consultar KeySet por completo. Los dos tienen el mismo efecto, por lo que no lo repetiré aquí para ahorrar espacio.
Conjunto de resumen público <Entry <K, V >> EntrySet ()
Se entrega un método abstracto a su subclase para completar, lo que indica que este método no es particularmente "general".
Público booleano iguales (objeto o)
El mapa estipula que solo cuando la clave y el valor de cada par de valores clave en el mapa corresponden uno por uno devolverán verdaderos. En el método, primero juzga las condiciones simples. Si las referencias son iguales, devuelva verdadero directamente. Si el parámetro O no es el tipo de mapa, devuelva falso directamente. Si el número de dos mapa es diferente, devuelva falso directamente. Solo entonces iterará sobre la matriz de entrada y comparará si la clave y el valor en la entrada corresponden uno por uno. El método es simple, pero esto nos da una inspiración. En el juicio condicional, primero debemos juzgar a los básicos simples y luego juzgar a los complejos.
Public int hashcode ()
Reescribir el método igual de la clase de objetos, y reescribir el hastre de hashcode también es necesario. La implementación de AbstractMap de hashcode es agregar los valores de hashcode de todos los map.Entry (aquí es SimpleEntry o SimpleMutableEntry) hasta el final, y la suma final se usa como el valor hashcode del mapa.
Cadena pública ToString ()
No hay nada que decir sobre este método, es eliminar todos los pares de valor clave y usar StringBuilder para empalmarlos.
Objeto protegido Clone () arroja clonenotsupportedException
Implemente una copia superficial, porque es una copia superficial de los valores y valores de teclas variables, evitando los problemas causados por las dos copias superficiales.