1. Colecciones en Java
Las clases de recolección en Java son las clases más utilizadas y más convenientes en la programación de Java. Como clase de contenedor, la clase de recolección puede almacenar cualquier tipo de datos y, por supuesto, también puede almacenar tipos especificados en combinación con genéricos (pero los genéricos solo son válidos durante el período de compilación y se borrarán en tiempo de ejecución). Lo que se almacena en la clase de colección es solo una referencia al objeto, no una referencia al objeto en sí. La capacidad de la clase de recolección se puede ampliar dinámicamente durante la operación, y también proporciona muchos métodos convenientes, como encontrar la unión y la intersección de la colección.
2. Estructura de clase de recolección
Las colecciones en Java incluyen múltiples estructuras de datos, como listas vinculadas, colas, tablas hash, etc. En términos de la estructura de herencia de una clase, se puede dividir en dos categorías. Uno se hereda de la interfaz de colección. Este tipo de colección incluye clases de colección como List, Set y Queue. La otra clase se hereda de la interfaz MAP, que incluye principalmente clases de recolección relacionadas con las tablas hash. Echemos un vistazo a los diagramas de la estructura de herencia de estas dos categorías:
1. Lista, configuración y cola
La línea punteada verde en la figura representa la implementación, la línea continua verde representa la herencia entre las interfaces, y la línea continua azul representa la herencia entre las clases.
(1) Lista: utilizamos más listas, incluidas ArrayList y LinkedList. La diferencia entre estos dos también es muy obvia, lo que se puede ver a partir de sus nombres. La lista de matrices subyacente se implementa a través de matrices, por lo que su velocidad de acceso aleatorio es relativamente rápida, pero la eficiencia es relativamente baja para los casos en que se requieren adiciones y deleciones frecuentes. Para LinkedList, la capa subyacente se implementa a través de listas vinculadas, por lo que la operación de adición y eliminación es más fácil de completar, pero la eficiencia del acceso aleatorio es relativamente baja.
Primero veamos la eficiencia de inserción de ambos:
paquete com.paddx.test.collection; import java.util.arrayList; import java.util.linkedList; public class ListTest {public static void main (string [] args) {for (int i =; i <; i ++) {} Long Start = System.CurrentTimemill (); LinkedList <ToGer> LinkedList <Integer> (); for (int i =; i <; i ++) {linkedList.add (, i);} long end = system.currentTimemillis (); system.println (final - inicio); arraylist <ineger> arraylist = new arrayList <DinGer> (); para (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (int (intent) i =; i <; i ++) {ArrayList.add (, i);} System.out.println (System.CurrentTimemillis () - End);}}Aquí están los resultados de la ejecución local:
veintitrés
1227
Se puede ver que en este caso, la eficiencia de inserción de LinkedList es mucho más alta que la de ArrayList, por supuesto, esta es una situación relativamente extrema. Comparemos la eficiencia del acceso aleatorio entre los dos:
paquete com.paddx.test.collection; import java.util.arrayList; import java.util.linkedList; import java.util.random; public class listTest {public static void main (string [] args) {random aleator = new Random (); for (int i =; i <; i ++) {} LinkedList <InteGeGerger LinkedList <Integer> (); for (int i =; i <; i ++) {LinkedList.Add (i);} ArrayList <Integer> ArrayList = new ArrayList <Integer> (); for (int i =; i <; i ++) {arrayList.add (i);} long start = system.currentTimemillis (); for (int i =; i <; i ++) {int j = random.nextint (i+); int k = linkedList.get (j);} largo end = system.currentTimemillis (); system.out.println (end - start); for (int i =; i <; i ++) {int j = random.nextint (i+); int k = int k = arrayList.get (j);} System.out.println (System.CurrentTimemillis () - End);}}Aquí está el resultado de mi ejecución:
5277
6
Es obvio que la eficiencia de acceso aleatorio de ArrayList es varios órdenes de magnitud más altos que LinkedList. A través de estas dos piezas de código, deberíamos poder saber más claramente la diferencia entre LinkedList y ArrayList y los escenarios de adaptación. En cuanto a Vector, es una versión segura de hilo de ArrayList, mientras que la pila corresponde a la estructura de datos de pila. Estos dos se usan con menos frecuencia, por lo que no daré un ejemplo aquí.
(2) cola: generalmente, se puede hacer directamente usando LinkedList. También se puede ver en el diagrama de clase anterior que LinkedList hereda de Deque, por lo que LinkedList tiene la función de una cola de doble extremo. Priorityqueue se caracteriza al proporcionar una prioridad para cada elemento, y los elementos con alta prioridad recibirán prioridad de la cola.
(3) Establecer: La principal diferencia entre el conjunto y la lista es que el conjunto no permite que los elementos se repitan, mientras que la lista puede permitir que los elementos se repitan. Para juzgar la repetición de elementos, debemos decidir en base al método hash del objeto y al método igual. Esta es también la razón por la cual generalmente anulamos el método hashcode e iguala el método para las clases de elementos en una colección. Tomemos un ejemplo para ver la diferencia entre el conjunto y la lista, así como el papel del método hashcode e igual al método:
paquete com.paddx.test.collection; import java.util.arrayList; import java.util.hashset; import java.util.set; public class settest {public static void main (string [] persona p1 = nueva persona ("lxp", 10); persona p2 = nueva persona ("lxp", 10); persona p3 = nueva p3 = nueva persona ("lxp", 10); persona p2 = nueva persona ("lxp", 10); persona p3 = nueva p3 = nueva persona ("lxp", 10); persona p2 = nueva persona ("lxp", 10); persona p3 = nueva persona p3 = nueva Persona ("LXP", 20); ArrayList <Oll> list = new ArrayList <Olli> (); list.add (p1); system.out.println ("-------------"); list.add (p2); system.out.println ("---------------"); list.add (p3); System.out.println ("Tamaño de lista de list (" " list.size());System.out.println("---------------");Set<Person> set = new HashSet<Person>();set.add(p1);System.out.println("------------");set.add(p2);System.out.println("-------------");set.add(p3);System.out.println("Set size = "+set.size ());} Persona de clase estática {private String Name; private int Age; public Person (String Name, int Age) {this.name = name; this.age = age;}@overRidePublic boolean iguales (objeto o) {System.Println (" llame a igual (); name = "+name); if (this == O) return; if ((if ((o == NATL (O == ! = o.getClass ()) return false; persona persona = (persona) o; return name.equals (persona.name);}@overridePublic int hashcode () {system.out.println ("llamar hashcode (), age ="+edad); return Age;}}}}}}}}}}} Los resultados de ejecución del código anterior son los siguientes:
------------
------------
Tamaño de la lista = 3
---- Línea de división ----
Llamar hashcode (), edad = 10
------------
Llamar hashcode (), edad = 10
Llamar igual (); nombre = lxp
------------
Llamar hashcode (), edad = 20
Tamaño establecido = 2
A partir de los resultados, no se realizan operaciones adicionales cuando el elemento se agrega a la lista y se puede repetir. Antes de unir SET, primero debe ejecutar el método hashcode. Si el valor devuelto ya existe en el conjunto, debe continuar ejecutando el método igual. Si el resultado devuelto por el método igual también es verdadero, demuestra que el elemento ya existe y el nuevo elemento será sobrescritado por el elemento anterior. Si el valor hashcode devuelto es diferente, agregará directamente el conjunto. Recuerde aquí que para los elementos en una colección, los elementos con diferentes valores de hashcode deben ser desiguales, pero para elementos con desiguales los valores de los hashcode pueden ser los mismos.
La diferencia entre hashset y Linkedhashset es que este último puede garantizar que el orden de los elementos insertados en el conjunto sea consistente con el orden de salida. La diferencia entre Tresset es que su tipo se clasifica en comparación y, por defecto, se organiza en orden ascendente en el orden natural de los caracteres.
(4) ITerable: de esta figura, puede ver que la clase de recolección hereda de Iterable. La función de esta interfaz es proporcionar un recorrido de elementos, es decir, todas las clases de colección (excepto las clases relacionadas con el mapa) proporcionan funciones transversales de elementos. ITerable contiene iterador iterador, y su código fuente es el siguiente. Si está familiarizado con el modo iterador, debería ser fácil de entender.
Public Interface Iterator <E> {boolean Hasnext (); e next (); void remove ();}2. Mapa:
La mayor ventaja de la colección de tipo de mapa es que su eficiencia de búsqueda es relativamente alta, y la complejidad del tiempo de O (1) se puede lograr idealmente. El mapa más utilizado es el hashmap. La diferencia entre LinkedHashmap y HashMap es que el primero puede garantizar que el orden de los elementos insertados en el conjunto sea consistente con el orden de salida. La diferencia entre estos dos y Treemap es que Treemap se clasifica de acuerdo con los valores clave. Por supuesto, su implementación subyacente también tiene diferencias esenciales. Por ejemplo, la capa subyacente de hashmap es una tabla hash, mientras que la capa subyacente de Treemap es un árbol. Veamos ahora la diferencia entre Treemap y Linkedhashmap:
paquete com.paddx.test.collection; import java.util.iterator; import java.util.linkedhashmap; import java.util.map; import java.util.treemeap; public class Maptest {public static void main (string [] args) {map <, string> treeMap = new treeTreM linkedmap = new LinkedHashMap <String, String> (); Treemap.put ("B", NULL); Treemap.put ("C", NULL); Treemap.put ("A", Null); para (Iterator <String> Iter = Treemap.KeySet (). Iterator (); iter.hasnext ();) {System.out.println ("Treemap ="+ITer.Next ());} System.out.prin tln ("---------- 分割线 ---------"); LinkedMap.put ("B", NULL); LinkedMap.put ("C", NULL); LinkedMap.put ("A", NULL); para (Iterator <String> iter = LinkedMap.KeySet (). Iterator (); iter.hasnext ();) {System.out.println ("Linkedhashmap ="+iter.next ());}} Ejecute el código anterior y el resultado de la ejecución es el siguiente:
Treemap = a
Treemap = b
Treemap = c
-------------------------
Linkedhashmap = B
Linkedhashmap = c
Linkedhashmap = a
A partir de los resultados de ejecución, es obvio que la diferencia entre Treemap y Linkedhashmap se ve claramente. El primero se emite mediante clasificación de cadenas, mientras que el segundo se emite mediante orden de inserción. Los lectores cuidadosos pueden encontrar que la diferencia entre HashMap y Treemap es consistente con las diferencias mencionadas anteriormente entre hashset y TreeSet. Al realizar el análisis del código fuente en el futuro, podemos ver que el hashset y el árbol de árboles se implementan esencialmente a través de HashMap y Treemap, respectivamente, por lo que sus diferencias son naturalmente las mismas. Hashtable rara vez se usa ahora. La principal diferencia de HASHMAP es que la hashtable es segura de subprocesos, pero debido a su baja eficiencia, el hashmap generalmente se usa. En un entorno multiproceso, CurrentHashMap generalmente se usa en su lugar.
3. Resumen
Este artículo solo presenta el marco de colección Java y su relación de herencia en su conjunto. Además de las clases anteriores, las colecciones también proporcionan dos clases de herramientas: colecciones y matrices. Además, la clasificación en la colección está estrechamente relacionada con comparable y comparador. En un artículo posterior, el código fuente de implementación de clase mencionado anteriormente en JDK se analizará en detalle.