JDK 1.2 introduce un nuevo marco para colecciones de objetos, llamado Java Collections Framework. "Oh, no", te quejas, "¡ni otra API, ni otro marco para aprender!" Pero espere, antes de que se aleje, escúcheme: el marco de Colecciones vale su esfuerzo y beneficiará su programación de muchas maneras. Inmediatamente me vienen a la mente tres grandes beneficios:
- Aumenta drásticamente la legibilidad de sus colecciones al proporcionar un conjunto estándar de interfaces para ser utilizado por muchos programadores en muchas aplicaciones.
- Hace que su código sea más flexible al permitirle pasar y devolver interfaces en lugar de clases concretas, generalizando su código en lugar de bloquearlo.
- Ofrece muchas implementaciones específicas de las interfaces, lo que le permite elegir la colección que más se ajusta y ofrece el mayor rendimiento para sus necesidades.
Y eso es solo para empezar.
Nuestro recorrido por el marco comenzará con una descripción general de las ventajas que ofrece para almacenar conjuntos de objetos. Como pronto descubrirá, debido a que sus viejos amigos caballos de batalla Hashtable
y Vector
admiten la nueva API, sus programas serán uniformes y concisos, algo que sin duda alegrará a usted y a los desarrolladores que acceden a su código.
Después de nuestra discusión preliminar, profundizaremos en los detalles.
La ventaja de las colecciones de Java: una descripción general
Antes de que Colecciones hiciera su debut más bienvenido, los métodos estándar para agrupar objetos Java eran a través de la matriz, el Vector
y el Hashtable
. Las tres colecciones tienen diferentes métodos y sintaxis para acceder a los miembros: las matrices usan los símbolos de corchetes ([]), Vector
usan el elementAt
método y Hashtable
usan get
y put
métodos. Estas diferencias han llevado a los programadores por el camino de la inconsistencia en la implementación de sus propias colecciones: algunos emulan los Vector
métodos de acceso y otros emulan la Enumeration
interfaz.
Para complicar aún más las cosas, la mayoría de los Vector
métodos están marcados como definitivos; es decir, no puede extender la Vector
clase para implementar un tipo de colección similar. Podríamos crear una clase de colección que se pareciera a a Vector
y actuara como a Vector
, pero no se podría pasar a un método que toma a Vector
como parámetro.
Finalmente, ninguna de las colecciones (matriz Vector
o Hashtable
) implementa una interfaz de acceso de miembros estándar. A medida que los programadores desarrollaban algoritmos (como géneros) para manipular colecciones, estalló un acalorado discurso sobre qué objeto pasar al algoritmo. ¿Deberías pasar una matriz o una Vector
? ¿Debería implementar ambas interfaces? Hable de duplicación y confusión.
Afortunadamente, Java Collections Framework soluciona estos problemas y ofrece una serie de ventajas sobre el uso de ningún marco o el uso de Vector
y Hashtable
:
Un conjunto utilizable de interfaces de colección
Mediante la implementación de una de las interfaces básicas -
Collection
,Set
,List
, oMap
- a garantizar que su clase se ajusta a una API común y se hace más regular y de fácil comprensión. Entonces, ya sea que esté implementando una base de datos SQL, un comparador de muestras de color o una aplicación de chat remota, si implementa laCollection
interfaz, sus usuarios conocen bien las operaciones en su colección de objetos. Las interfaces estándar también simplifican el paso y la devolución de colecciones hacia y desde métodos de clase y permiten que los métodos funcionen en una variedad más amplia de colecciones.Un conjunto básico de implementaciones de colecciones
Además de los confiables
Hashtable
yVector
, que se han actualizado para implementar lasCollection
interfaces, se han agregado nuevas implementaciones de colección, que incluyenHashSet
yTreeSet
,ArrayList
yLinkedList
, yHashMap
yMap
. El uso de una implementación común existente hace que su código sea más corto y más rápido de descargar. Además, el uso del núcleo de código Core Java existente garantiza que cualquier mejora en el código base también mejorará el rendimiento de su código.Otras mejoras útiles
Cada colección ahora devuelve un
Iterator
tipo mejorado deEnumeration
que permite operaciones de elementos como inserción y eliminación. ElIterator
es "a prueba de rápido", que significa que tienes una excepción si la lista que estás iteración se cambia por otro usuario. Además, las colecciones basadas en listas, comoVector
return a,ListIterator
permiten la iteración y actualización bidireccional.Varias colecciones (
TreeSet
yTreeMap
) apoyan implícitamente los pedidos. Utilice estas clases para mantener una lista ordenada sin esfuerzo. Puede encontrar los elementos más pequeños y más grandes o realizar una búsqueda binaria para mejorar el rendimiento de listas grandes. Puede ordenar otras colecciones proporcionando un método de comparación de colecciones (unComparator
objeto) o un método de comparación de objetos (laComparable
interfaz).Por último, una clase estática
Collections
proporciona versiones no modificables (solo lectura) y sincronizadas de colecciones existentes. Las clases no modificables son útiles para evitar cambios no deseados en una colección. La versión sincronizada de una colección es una necesidad para los programas multiproceso.
Java Collections Framework es parte de Core Java y está incluido en el java.util.collections
paquete de JDK 1.2. El marco también está disponible como paquete para JDK 1.1 (ver Recursos).
Nota: Se nombra la versión de colecciones JDK 1.1 com.sun.java.util.collections
. Tenga en cuenta que el código desarrollado con la versión 1.1 debe actualizarse y recompilarse para la versión 1.2, y los objetos serializados en 1.1 no se pueden deserializar en 1.2.
Veamos ahora más de cerca estas ventajas ejercitando el marco de colecciones de Java con algún código propio.
Una buena API
La primera ventaja de Java Collections Framework es una API regular y consistente. La API está codificada en un conjunto básico de interfaces, Collection
, Set
, List
, o Map
. La Collection
interfaz contiene operaciones básicas de recopilación, como agregar, eliminar y probar la pertenencia (contención). Cualquier implementación de una colección, ya sea una proporcionada por Java Collections Framework o una de sus propias creaciones, admitirá una de estas interfaces. Debido a que el marco de Colecciones es regular y consistente, aprenderá una gran parte de los marcos simplemente aprendiendo estas interfaces.
Ambos Set
e List
implementar la Collection
interfaz. La Set
interfaz es idéntica a la Collection
interfaz excepto por un método adicional toArray
, que convierte Set
a en una Object
matriz. La List
interfaz también implementa la Collection
interfaz, pero proporciona muchos accesos que usan un índice entero en la lista. Por ejemplo, get
, remove
, y set
todos tomar un número entero que afecta al elemento de indexado de la lista. La Map
interfaz no se deriva de la colección, pero proporciona una interfaz similar a los métodos de java.util.Hashtable
. Las claves se utilizan para poner y obtener valores. Cada una de estas interfaces se describe en los siguientes ejemplos de código.
El siguiente segmento de código demuestra cómo realizar muchas Collection
operaciones en HashSet
una colección básica que implementa la Set
interfaz. A HashSet
es simplemente un conjunto que no permite elementos duplicados y no ordena ni coloca sus elementos. El código muestra cómo crear una colección básica y agregar, eliminar y probar elementos. Como Vector
ahora admite la Collection
interfaz, también puede ejecutar este código en un vector, que puede probar cambiando la HashSet
declaración y el constructor a Vector
.
importar java.util.collections. *; public class CollectionTest {// Estática public static void main (String [] args) {System.out.println ("Collection Test"); // Crea una colección HashSet collection = new HashSet (); // Añadiendo String dog1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; colección.add (perro1); collection.add (perro2); colección.add (perro3); // Dimensionamiento System.out.println ("Colección creada" + ", size =" + collection.size () + ", isEmpty =" + collection.isEmpty ()); // Containment System.out.println ("La colección contiene" + dog3 + ":" + colección.contains (dog3)); // Iteración. El iterador admite hasNext, luego, elimina System.out.println ("Iteración de la colección (sin clasificar):"); Iterador iterador = colección.iterador (); while (iterador.hasNext ()) System.out.println ("" + iterator.next ()); // Eliminando collection.remove (dog1); colección.clear (); }}
Construyamos ahora sobre nuestro conocimiento básico de colecciones y veamos otras interfaces e implementaciones en Java Collections Framework.
Buenas implementaciones concretas
Hemos ejercido la Collection
interfaz en una colección concreta, el HashSet
. Veamos ahora el conjunto completo de implementaciones de colecciones concretas proporcionadas en el marco de colecciones de Java. (Consulte la sección Recursos para obtener un enlace al esquema anotado de Sun del marco de las colecciones de Java).
Implementaciones | ||||||
---|---|---|---|---|---|---|
Tabla de picadillo | Matriz de tamaño variable | Árbol equilibrado (ordenado) | Lista enlazada | Legado | ||
Interfaces | Conjunto | HashSet | * | TreeSet | * | * |
Lista | * | Lista de arreglo | * | Lista enlazada | Vector | |
Mapa | HashMap | * | TreeMap | * | Tabla de picadillo |
Implementations marked with an asterix (*) make no sense or provide no compelling reason to implement. For instance, providing a List
interface to a Hash Table makes no sense because there is no notion of order in a Hash Table. Similarly, there is no Map
interface for a Linked List because a list has no notion of table lookup.
Let's now exercise the List
interface by operating on concrete implementations that implement the List
interface, the ArrayList
, and the LinkedList
. The code below is similar to the previous example, but it performs many List
operations.
import java.util.collections.*; public class ListTest { // Statics public static void main( String [] args ) { System.out.println( "List Test" ); // Create a collection ArrayList list = new ArrayList(); // Adding String [] toys = { "Shoe", "Ball", "Frisbee" }; list.addAll( Arrays.toList( toys ) ); // Sizing System.out.println( "List created" + ", size=" + list.size() + ", isEmpty=" + list.isEmpty() ); // Iteration using indexes. System.out.println( "List iteration (unsorted):" ); for ( int i = 0; i < list.size(); i++ ) System.out.println( " " + list.get( i ) ); // Reverse Iteration using ListIterator System.out.println( "List iteration (reverse):" ); ListIterator iterator = list.listIterator( list.size() ); while ( iterator.hasPrevious() ) System.out.println( " " + iterator.previous() ); // Removing list.remove( 0 ); list.clear(); } }
As with the first example, it's simple to swap out one implementation for another. You can use a LinkedList
instead of an ArrayList
simply by changing the line with the ArrayList
constructor. Similarly, you can use a Vector
, which now supports the List
interface.
When deciding between these two implementations, you should consider whether the list is volatile (grows and shrinks often) and whether access is random or ordered. My own tests have shown that the ArrayList
generally outperforms the LinkedList
and the new Vector
.
Notice how we add elements to the list: we use the addAll
method and the static method Arrays.toList
. This static method is one of the most useful utility methods in the Collections framework because it allows any array to be viewed as a List
. Now an array may be used anywhere a Collection
is needed.
Notice that I iterate through the list via an indexed accessor, get
, and the ListIterator
class. In addition to reverse iteration, the ListIterator
class allows you to add, remove, and set any element in the list at the point addressed by the ListIterator
. This approach is quite useful for filtering or updating a list on an element-by-element basis.
La última interfaz básica en Java Collections Framework es Map
. Esta interfaz se implementa con dos nuevas implementaciones concretas, el TreeMap
y el HashMap
. El TreeMap
es una aplicación árbol equilibrado que ordena los elementos de la llave.
Ilustremos el uso de la Map
interfaz con un ejemplo simple que muestra cómo agregar, consultar y borrar una colección. Este ejemplo, que usa la HashMap
clase, no es muy diferente de cómo usamos el Hashtable
antes del debut del marco de Colecciones. Ahora, con la actualización de Hashtable
para admitir la Map
interfaz, puede cambiar la línea que crea HashMap
una instancia de y reemplazarla con una instancia de Hashtable
.