Genéricos y Colecciones

A continuación dejo el resumen del séptimo capítulo (Generics and Collections) del libro "Sun Certified Programmer for Java 6 Study Guide".

Sobreescribiendo hashCode() y equals() (Objetivo 6.2):
Métodos de la clase Object que se necesitan saber para el examen:
  • boolean equals(Object obj)
  • void finalize()
  • int hashCode()
  • final void notify()
  • final void notifyAll()
  • final void wait()
  • String toString()
Método equals()
El operador == permite evaluar si dos referencias son iguales, es decir, cuando se refieren al mismo objeto. Para comparar si dos objetos son iguales, si los objetos en sí mismo son idénticos, se utiliza el método equals().
La clase String y todas las clases envoltorios (wrappers) de tipos primitivos, tienen el método equals() redefinido. Por esto mismo se pueden comparar si dos objetos tienen un mismo estado.
Si se quiere utilizar (de manera correcta) un objeto como clave en una colección hash, se debe sobreescribir el método equals(), para de este modo permitir considerar dos instancias iguales.

Método hashCode()
Generalmente los hashcodes son utilizados para mejorar la performance de grandes colecciones de información. Este código se utiliza para determinar donde se guardará el objeto dentro de una colección (HashMap, HashSet o sus subtipos), y como se debe localizar. Para el examen se debe saber que colecciones lo utilizan, y diferenciar los usos apropiados o correctos de los legales.

Colecciones (Objetivo 6.1):
Tipos de colecciones:
  • List: Sus operaciones están basadas en los índices de los elementos en la colección. Todas sus implementaciones tienen sus índices ordenados. Cuando se agrega un elemento a la colección se puede hacer especificando el índice en el cual tiene que estar, o sin especificarlo (en este caso se posiciona al final).
    - ArrayList: Provee una rápida iteración y un rápido acceso aleatorio. Pero es más lento para insertar y quitar elementos que LinkedList.
    - Vector: Es una colección primitiva de las primeras versiones de java. Es básicamente similar a ArrayList, salvo que todos sus métodos están sincronizados para el manejo seguro de hilos (thread safe).
    - LinkedList: Es una colección como ArrayList, excepto porque sus elementos se encuentran doblemente ligados (uno con otro). Este doble vinculo otorga nuevos métodos para agregar o quitar elementos del principio o el final. Su iteración es más lenta que ArrayList. A partir de Java 5, esta colección implementa la interface Queue. De esta manera puede ser tratada como una cola, y posee los métodos: peek(), poll() y offer().
  • Set: Es un conjunto de elementos únicos. Es decir, no se permiten objetos duplicados. Para lograr este comportamiento se utiliza el método equals(), que permite verificar si dos instancias son idénticas.
    - HashSet: Es una colección que no mantiene un orden específico. Utiliza el código de hash de los objetos insertados. Por este motivo mientras más eficiente sea la implementación del método hashCode(), mejor será la performance de acceso. Es útil cuando se necesita una colección sin elementos duplicados y en la cual no importe el orden de iteración.
    - LinkedHashSet: Es la versión ordenada de HashSet. Mantiene un doble enlace entre sus elementos como si fuera una lista. Es útil cuando se necesita (a diferencia de HashSet) una colección en donde el orden de iteración sea importante.
    - TreeSet: Es una colección que contiene sus elementos ordenados. Utiliza un árbol de estructura rojo-negro, y garantiza que los elementos se encuentren en orden ascendente, de acuerdo a su orden natural. A partir de Java 6, esta colección implementa NavigableSet.
  • Map: Son colecciones con elementos compuestos de parejas clave/valor. Las claves de los elementos son únicas. Al igual que la interface Set, utiliza el método equals() para determinar si dos objetos son iguales. Muchas de sus operaciones están basadas en las claves.
    - HashMap: Es una colección que no mantiene un orden específico. Utiliza el código de hash sobre las claves, para determinar el orden de sus elementos. Es útil cuando se necesita un mapa en el cuál no importe el orden de iteración. Permite un solo valor null como clave, y multiples valores null en la colección.
    - Hastable: Como la clase Vector, es una implementación de las primeras versiones de java. Es similar a HashMap, a diferencia que sus métodos se encuentran sincronizados. Otra de las diferencias es que no permite valores null tanto en la claves como en los valores.
    - LinkedHashMap: Similar a HashMap, a diferencia que mantiene los elementos ordenados. Y porque es un poco más lento para agregar o quitar elementos de la colección. Pero permite una iteración más veloz.
    - TreeMap: Es un mapa ordenado de forma natural. También permite definir un tipo de orden (a través de las interfaces Comparable y Comparator). A partir de Java 6, implementa la interface NavigableMap.
  • Queue: Es una colección de tipo “cola”, la cual permite almacenar cosas que deben ser procesadas de cierta manera. Generalmente funcionan como colas FIFO (First-In, First-Out).
    - PriorityQueue: Es una clase nueva de Java 5. Generalmente se utiliza la clase LinkedList para implementar colas. Pero el propósito de esta colección, es crear colas con prioridades, a diferencia de las colas FIFO. Sus elementos se encuentran ordenados por orden natural, o de acuerdo a un objeto Comparator. El orden de los elementos representa la prioridad.
Ordenando colecciones
Las clases Arrays y Collections poseen un método para ordenar sus elementos. Arrays.sort() y Collections.sort(). La única condición que deben cumplir los elementos del arreglo, es que sean del mismo tipo. Objetos de diferentes tipos no son mutuamente comparables.

java.lang.Comparable
Para que una colección de objetos pueda ser ordenada, los mismos deben implementar las interface Comparable. Dicha interface solo posee el método compareTo().
thisObject.compareTo(anotherObject);
Este método devuelve un valor entero con las siguientes características:
  • Negativo: thisObject < anotherObject
  • Cero: thisObject == anotherObject
  • Positivo: thisObject > anotherObject
La interface Comparable (a partir de Java 5) permite utilizar un tipo genérico. De esta manera no se deben realizar casteos en ninguna parte del código. Cada clase que implemente la interface, definirá el tipo de objeto con el que trabajara.
public int compareTo(T o);

java.util.Comparator
Existe una versión sobrecargada del método Collections.sort(), la cual permite pasar como argumento un objeto Comparator. La interface Comparator brinda la capacidad de ordenar una colección de diferentes maneras. Para utilizar esta interface, se debe declarar una nueva clase que la implemente, y sobrescriba el método compare(). Al igual que Comparable puede utilizar un tipo parametrizado (lo cual no es obligatorio, pero generará advertencias al momento de la compilación).
public int compare(T o1, T o2);

Arrays.sort()
La clase Arrays (al igual que Collections) posee dos versiones del método sort():
• Arrays.sort(arrayToSort): Para cualquier tipo de objeto o tipos primitivos.
• Arrays.sort(arrayToSort, Comparator): se puede utilizar solo para objetos (NO primitivos).

Buscando elementos en las colecciones
Las clases Collections y Arrays poseen un método que permite buscar un elemento específico, binarySearch(). Las búsquedas exitosas devuelven el valor entero del índice del elemento, las que no tienen éxito devuelven un entero negativo que representa el lugar de inserción. Es obligatorio que la colección se encuentre ordenada antes de realizar cualquier búsqueda, caso contrario se devolverá un valor impredecible. Si la colección ha sido ordenada mediante un objeto Comparator, la búsqueda debe realizarse pasando como segundo parámetro el mismo objeto Comparator.
Los siguientes métodos pertenecen tanto a Arrays como a Collections:
• binarySearch(ObjetoBuscado o)
• binarySearch(ObjetoBuscado o, Comparable c)

Convirtiendo arreglos a listas y listas a arreglos
Las interfaces List y Set poseen el método toArray(), el cual convierte la lista de elementos en un arreglo. La clase Arrays tiene un método llamado asList(), este copia el contenido de un arreglo adentro de una lista.
Cuando se actualiza un elemento de algunas de las dos colecciones, automáticamente se actualiza la otra.

Iterator
Es un objeto que está asociado con una colección específica. Permite iterar a través de la colección paso a paso. Los dos métodos de la interface Iterator que se deben saber para el examen son:
  • boolean hasNext(): Devuelve true si hay al menos un elemento más en la colección que se esta atravesando.
  • Object next(): Devuelve el próximo objeto en la colección, y mueve hacia adelante el puntero.
Se puede utilizar un tipo parametrizado junto al objeto Iterator, de esta menara el método next() devolverá dicho tipo, evitando las necesidades de casteo.

Set
Se debe prestar atención el tipo de implementación que se utiliza. Una colección HashSet permite contener elementos de diferentes tipos (si el tipo parametrizado es Object, o el mismo se excluye). Pero una colección TreeSet (la cual contiene a sus elementos en orden) no permite contener objetos que no sean comparables entre sí.

Map
A la hora de utilizar este tipo de colecciones, se debe prestar atención a las claves utilizadas. Es decir, si un objeto clave (insertado en la colección) luego modifica su estado, puede ser que el mismo no sea hallado en el mapa. Esta situación se da debido a que el método hashCode(), devuelve un código diferente.

NavigableSet
Esta interface (implementada únicamente por TreeSet) posee diversos métodos de utilidad:
  • lower(): Devuelve el elemento menor al elemento pasado como parámetro.
  • floor(): Devuelve el elemento menor o igual al elemento pasado como parámetro.
  • higher(): Devuelve el elemento mayor al elemento pasado como parámetro.
  • ceiling(): Devuelve el elemento mayor o igual al elemento pasado como parámetro.
  • pollFirst(): Devuelve el primer elemento y lo elimina de la colección.
  • pollLast(): Devuelve el último elemento y lo elimina de la colección.
  • descendingSet(): Devuelve una copia de la colección en orden inverso.
  • headSet(e): Devuelve un subconjunto que termina en el elemento (excluido) e.
  • tailSet(e): Devuelve un subconjunto que comienza en el elemento (incluido) e.
  • subSet(s, e): Devuelve un subconjunto que comienza en el elemento (incluido) s y finaliza en el elemento (excluido) e.
NavigableMap
Esta interface (implementada únicamente por TreeMap) posee diversos métodos de utilidad:
  • lowerKey(): Devuelve la clave menor a la clave pasada como parámetro.
  • floorKey(): Devuelve la clave menor o igual a la clave pasada como parámetro.
  • higherKey(): Devuelve la clave mayor a la clave pasada como parámetro.
  • ceilingKey(): Devuelve la clave mayor o igual a la clave pasada como parámetro.
  • pollFirstEntry(): Devuelve la primer pareja clave/valor y la elimina de la colección.
  • pollLastEntry(): Devuelve la ultima pareja clave/valor y la elimina de la colección.
  • descendigMap(): Devuelve una copia de la colección en orden inverso.
  • headMap(k): Devuelve un subconjunto que termina en la clave (excluida) k.
  • tailMap(k): Devuelve un subconjunto que comienza en la clave (incluida) k.
  • subMap(s, e): Devuelve un subconjunto que comienza en la clave (incluida) s y finaliza en la clave (excluida) e.
Queue
La colección PriorityQueue ordena sus elementos utilizando una prioridad definida por el usuario. La prioridad puede ser el orden natural, pero también se puede ordenar utilizando un objeto Comparator. La interface Queue posee métodos que no se encuentran en ninguna otra colección:
  • peek(): Devuelve el primer elemento de la cola (o el que tenga mayor prioridad).
  • poll(): Devuelve el primer elemento de la cola (o el que tenga mayor prioridad), y luego lo elimina de la cola.
  • offer(T o): Agrega un elemento al final de la cola (o en el lugar donde indique su prioridad).
RESUMEN: TWO-MINUTE DRILL
Sobrescribiendo hashCode() y equals() (Objetivo 6.2):
  • Los métodos equals(), hashCode() y toString() son públicos.
  • El método toString() permite mostrar el estado de un objeto mediante un String.
  • El operador == sirve para determinar si dos variables de referencia apuntan al mismo objeto.
  • El método equals() sirve para determinar si dos objetos poseen un estado equivalente.
  • Si no se sobrescribe el método equals(), los objetos no serán útiles como claves hash.
  • Si no se sobrescribe el método equals(), objetos diferentes no pueden ser considerados iguales.
  • La clase String y las clases envoltorios (wrappers) sobrescriben equals() y son claves hash eficientes.
  • Cuando se sobrescribe el método equals(), es conveniente utilizar el operador instanceof para estar seguro de que se está evaluando un objeto correcto.
  • Cuando se sobrescribe el método equals(), es conveniente comprar los atributos significantes del objeto.
  • Los características más importantes del método equals() son:
    - Es reflexivo: x.equals(x) es true.
    - Es simétrico: Si x.equals(y) es true, entonces y.equals(x) debe ser true.
    - Es transitivo: Si x.equals(y) es true, y y.equals(z) es true, entonces z.equals(x) es true.
    - Es consistente: Múltiples llamadas a x.equals(y) deben retornar el mismo resultado.
    - Null: Si x no es null, entonces x.equals(null) es false.
  • Si x.equals(y) es true, entonces x.hashCode() == y.hashCode() es true.
  • Si se sobrescribe equals(), es aconsejable sobrescribir hashCode().
  • HashMap, Hashtable, LinkedHashMap, HashSet y LinkedHashSet utilizan el código de hash.
  • Un hashCode() apropiado debe cumplir el contrato del método.
  • Un hashCode() eficiente debe retornar valores diferentes para distribuir a través de todas las claves.
  • El método equals() debe ser precioso como hashCode(), es decir, se deben utilizar las mismas variables de instancia para llevar a cabo sus operaciones.
  • Es legal que el método hashCode() devuelva el mismo valor para todas las instancias de una clase. Salvo que en la práctica esto no es eficiente.
  • Los características más importantes del método hashCode() son:
    - Es consistente: Múltiples llamados a x.hashCode() devuelven el mismo valor entero.
    - Si x.equals(y) es true, x.hashCode() == y.hashCode() es true.
    - Si x.equals(y) es false, entonces x.hashCode() == y.hashCode() puede ser tanto true como false, pero si es false la implementación tiende a tener mayor eficiencia.
  • Las variables de instancia transient son inapropiadas para utilizar en equals() y hashCode().
Colecciones (Objetivo 6.1):
  • Las acciones comunes sobre las colecciones son añadir elementos, eliminarlos, verificar su inclusión, obtenerlos y iterar sobre los mismos.
  • Existen cuatro tipos básicos de colecciones:
    - Lists
    - Sets
    - Maps
    - Queues
  • El ordenamiento puede ser alfabético, numérico o definido por el usuario.
Atributos clave de las clases de colección (Objetivo 6.1):
  • ArrayList: Rápida iteración y rápido acceso aleatorio.
  • Vector: Es como un ArrayList más lento, pero tiene sus métodos sincronizados.
  • LinkedList: Es bueno para agregar elementos al final, por ejemplo pilas y colas.
  • HashSet: Rápido acceso, asegura la no duplicación, no provee un orden.
  • LinkedHashSet: No posee elementos duplicados, itera por orden de inserción.
  • TreeSet: No posee elementos duplicados, itera en orden.
  • HashMap: Rápidas actualizaciones (clave/valor), permite una clave null y muchos valores null.
  • Hashtable: Es como un HashMap más lento, pero tiene sus métodos sincronizados. No permite valores null tanto en las claves como en los valores.
  • LinkedHashMap: Rápidas iteraciones, itera en orden de inserción o ultimo acceso. También permite valores null y una clave null.
  • TreeMap: Un mapa ordenado.
  • PriorityQueue: Una cola ordenada con las prioridades de sus elementos.
Utilizando las clases de colección (Objetivo 6.3):
  • Las colecciones pueden almacenar solo objetos, pero las primitivas pueden ser convertidas automáticamente a sus tipos envoltorios (autoboxed).
  • Las iteraciones se pueden realizar a través del operador for (nuevo) o con un objeto Iterator a través de los métodos hasNext() y next().
  • El método hasNext() determina si existen más elementos, el iterador no se mueve.
  • El método next() devuelve el siguiente elemento y mueve el iterador hacia adelante.
  • Para trabajar de manera eficiente, los objetos clave de un mapa deben sobrescribir el método equals() y hashCode().
  • Las colas utilizan el método offer() para añadir elementos, poll() para devolver y eliminar el elemento inicial, y peek() para obtener el elemento inicial.
  • A partir de Java 6 las clases TreeSet y TreeMap tienen nuevos métodos de navegación como floor() y higher().
  • Se pueden crear/extender sub-copias “respaldadas” de TreeSets y TreeMaps.
Ordenando y buscando en Arrays y Lists (Objetivo 6.5):
  • La ordenación se puede realizar en orden natural, o a través de un objeto Comparable o muchos Comparators.
  • Para implementar Comparable se debe utilizar el método compareTo(), el cual provee solo un modo de ordenación.
  • Se pueden crear muchos Comparators para ordenar una clase de diversas maneras, implementando el método compare().
  • Para que los elementos de una lista (List) puedan ser ordenados y buscados, los mismos deben ser comparables.
  • Para buscar elementos en un arreglo o lista, los elementos deben estar ordenados.
Clases de utilidad: Collections y Arrays (Objetivo 6.5):
  • Estas dos clases pertenecen al paquete java.util, y las mismas proveen:
    - Un método sort(). El cual ordena los elementos en orden natural o a través de un objeto Comparator.
    - Un método binarySearch(). Para buscar un elemento en un arreglo o lista previamente ordenado.
    - El método Arrays.asList crea una lista (List) a partir de un arreglo.
    - El método Collections.reverse() invierte el orden de los elementos de una lista.
    - El método Collections.reverseOrder() devuelve un Comparator que ordena inversamente.
    - Las interfaces List y Set poseen el método toArray() que convierte la colección en un arreglo.
Genéricos (Objetivo 6.4):
  • Los tipos genéricos permiten forzar la seguridad de los tipos, en tiempo de compilación, en las colecciones (o otras clases y métodos que utilicen tipos parametrizados).
  • Un ArrayList<T> permite almacenar objetos T o cualquier subtipo del mismo. (T también puede ser una interface).
  • Cuando se utilizan colecciones genéricas, no es necesario castear los objetos cuando se obtienen de la misma.
  • Se puede pasar una colección genérica como parámetro a un método que toma una colección no genérica, pero los resultados pueden ser inesperados.
  • Compilar sin ningún error no es lo mismo que compilar sin ninguna advertencia. Una advertencia de compilación no es considerado un error de compilación.
  • La información genérica de tipo no existe en tiempo de ejecución, es solo para la seguridad de tipos en tiempo de compilación. Mesclando genéricos con código legal se puede compilar correctamente, pero dicho código puede arrojar una excepción.
  • Las asignaciones polimórficas aplican solo al tipo base, no al parámetro de tipo genérico:
    - List<Animal> l = new ArrayList<Animal>(); // valido
    - List<Animal> l = new ArrayList<Dog>(); // inválido
  • La regla de asignación polimórfica aplica en cualquier lugar en donde se pueda realizar una asignación:
    - void foo(List<Animal> l) { } // no puede tomar un argumento List<Dog>
    - List<Animal> bar() { } // no puede devolver un List<Dog>
  • La sintaxis comodín permite a un método genérico, aceptar subtipos (o supertipos) de un tipo declarado como argumento de método: List<? extends Animal>
  • Cuando se utiliza un comodin <? extends Dog>, la colección puede ser accedida pero no modificada.
  • Cuando se utiliza el comodin List<?>, cualquier tipo genérico puede ser asignado a la referencia, pero solo para acceso, no para modificaciones.
  • List<?> es igual a List<? extends Object>.
  • Las convenciones de declaración utilizan la letra T para tipos y E para elementos de una colección.
  • Se puede utilizar más de un tipo parametrizado en una declaración.
  • Se puede declarar un tipo genérico utilizando un tipo que no esté definido en la clase: public <T> void makeList(T t) { }

Almacenamiento de objetos (Contenedores)

Resumen del capítulo 11 (Almacenamiento de objetos) del "Libro Thinking in Java (4ta Edición)".

Introducción

La biblioteca java.util posee un conjunto bastante completo de clases contenedoras. Existen cuatro tipo básicos: List, Set, Queue y Map (lista, conjunto, cola y mapa). Los contenedores proporcionan formas más sofisticadas (que las matrices) de almacenar objetos.
La biblioteca de contenedores Java toma la idea de “almacenamiento de los objetos” y la divide en dos conceptos distintos, expresados mediante las interfaces básicas de la biblioteca:
  • Collection: una secuencia de elementos individuales a los que se aplica una o más reglas.
    - List: almacena los elementos en la forma en la que fueron insertados.
    - Set: no puede tener elementos duplicados.
    - Queue: produce los elementos en el orden determinado por una disciplina de cola.
  • Map: un grupo de parejas de objetos clave-valor, que permite efectuar búsquedas de valores utilizando una clase. Un mapa permite buscar un objeto utilizando otro objeto. También se lo denomina matriz asociativa o diccionario.
Estas interfaces utilizan tipos genéricos, es decir, se debe especificar el tipo de objeto/s que almacenará el contenedor. Esto se realiza a través de corchetes angulares que rodean los parámetros de tipo.
De ser posible, se debe intentar escribir la mayor parte del código para que se comunique con estas interfaces. El único lugar donde se debería especificar el tipo concreto del contenedor es en la creación del mismo.
Ver ejemplo: Main01.java

Existen métodos de utilidad en las clases Arrays y Collections de java.util que añaden grupos de elementos a una colección:
  • Collections.addAll (Collection c, T… elements): toma un objeto de tipo Collection como primer argumento y una lista de valores separados por coma. Añade los elementos a la colección.
  • Arrays.asList (T… a): toma una lista de valores separados por coma y lo transforma en un objeto List.
Ver ejemplo: Main02.java

List

Las listas garantizan que los elementos se mantengan en una secuencia concreta. La interface List añade varios métodos a Collection que permiten la inserción y la eliminación de elementos en mitad de una lista.
Existen dos tipos de objetos List:
  • ArrayList: Es el que mejor permite acceder a los elementos de forma aleatoria, pero que resulta más lento a la hora de insertar y eliminar elementos en mitad de una lista.
  • LinkedList: Proporciona un acceso secuencial óptimo, siendo las inserciones y borrados en mitad de una lista enormemente rápidos. Resulta relativamente lento para los accesos aleatorios, pero tiene muchas más funcionalidades que ArrayList.
Métodos de la interface:
  • boolean contains(Object o): Permite averiguar si un objeto se encuentra dentro de la lista.
  • boolean remove(Object o): Permite eliminar un objeto, pasando la referencia al mismo.
  • int indexOf(Object o): Pasando como parámetro una referencia a un objeto, devuelve el número de índice en el que ese objeto está almacenado.
Estos últimos tres métodos utilizan el método equals() para realizar sus operaciones. Es decir, sobrescribiendo este método (perteneciente a la clase Object) se puede alterar el funcionamiento de estas operaciones.
  • List subList(int fromIndex,int toIndex): Permite crear una sublista (respaldada) a partir de otra lista de mayor tamaño. Los cambios efectuados en la lista devuelta se verán reflejados en la lista original, y viceversa.
  • boolean containsAll(Collection c): Verifica si los elementos pertenecen a la lista.
  • boolean retainAll(Collection c): Es una operación de intersección de conjuntos, el comportamiento resultante depende de la implementación del método equals().
  • boolean removeAll(Collection c): Elimina de la lista todos los objetos que estén en el argumento de tipo List. También opera de manera distinta dependiendo del método equals().
  • boolean isEmpty(): Devuelve true si la lista se encuentra vacía.
  • void clear(): Elimina todos los elementos de la lista.
  • E set(int index, E element): Se encarga de sustituir el elemento situado en el índice indicado (el primer argumento) con el segundo argumento.
Ver ejemplo: Main03.java

Set

Los objetos de tipo Set (conjuntos) no permiten almacenar más de una instancia de cada objeto, impide la duplicación. Para insertar un nuevo elemento se debe verificar la no pertenencia, por este motivo la operación más importante de un conjunto suele ser el de la búsqueda. Set tiene la misma interfaz que Collection, por lo que no existe ninguna funcionalidad adicional.
Existen tres tipos de contenedores Set:
  • HashSet: Utiliza el mecanismo de hash para acelerar las búsquedas de elementos.
  • TreeSet: Mantiene los elementos ordenados en una estructura de datos de tipo árbol rojo-negro. Este objeto es útil para mantener los objetos ordenados.
  • LinkedHashSet: Es un subtipo de HashSet, por lo tanto también emplea una función hash para acelerar las búsquedas, pero mantiene los elementos en orden de inserción utilizando una lista enlazada.
Ver ejemplo: Main04.java

Queue

Una cola es normalmente un contenedor de tipo FIFO (first-in, first-out). El orden en el que se introduzcan los elementos coincidirá con el orden en que estos serán extraídos. Las colas son especialmente importantes en la programación concurrente.
Existen dos tipos de contenedores Queue:
  • LinkedList: Dispone de métodos para soportar el comportamiento de una cola e implementa la interface Queue, por lo que un objeto LinkedList puede utilizarse como implementación de Queue.
  • PriorityQueue: Es una implementación automática de una cola con prioridad. Este tipo de contenedor implica que el elemento que va a continuación será aquel que tenga una necesidad mayor (la prioridad más alta). El mecanismo de ordenación predeterminado utiliza el orden natural de los objetos de la cola, pero se puede modificar dicho elemento proporcionando otro objeto Comparator.
Arroja una excepción Retorna un valor especial
Inserta boolean add(E e) boolean offer(E e)
Elimina E remove() E poll()
Obtiene E element() E peek()

Ver ejemplo: Main05.java

Map

Los mapas permiten asociar objetos con otros objetos. Es decir, almacenan parejas de clave-valor. En los contenedores no se pueden almacenar primitivas, por eso la característica autoboxing convierte las primitivas en sus correspondientes objetos envoltorios. Este tipo de contenedores puede expandirse fácilmente para que sean multidimensionales, basta con definir un objeto Map cuyos valores sean también mapas.
Existen tres tipos de contenedores Map:
  • HashMap: Están diseñados para un acceso rápido.
  • TreeMap: Mantiene sus claves ordenadas y no es tan rápido como el anterior.
  • LinkedHashMap: Mantiene sus elementos en orden de inserción, pero proporciona un acceso rápido con mecanismos de hash.
Métodos de la interface:
Ver ejemplo: Main06.java

Iteradores

Iterator
Es una interface que permite desplazarse a través de una secuencia y seleccionar cada uno de los objetos que la componen.
  • boolean hasNext(): Permite ver si hay más objetos en la secuencia.
  • E next(): Obtiene el siguiente objeto de la secuencia.
  • void remove(): Elimina el último elemento devuelto por el iterador.
ListIterator
Es un subtipo más potente de Iterator que solo se genera mediante las clases List. ListIterator es bidireccional, puede generar los índices de los elementos siguiente y anterior, en relación al lugar de la lista hacia el que el iterador está apuntando y también posee otras funcionalidades. Los métodos que adiciona esta interface son:
  • boolean hasPrevious(): Realiza la misma acción que hasNext() pero en sentido contrario.
  • E previous(): Idem next() pero en sentido contrario.
  • int nextIndex(): Obtiene el número de índice del elemento siguiente.
  • int previousIndex(): Obtiene el número de índice del elemento anterior.
  • void set(E e): Permite sustituir el elemento al que apunta por el iterador.
  • void add(E e): Inserta un elemento en la lista.
NOTA: NO HAY NECESIDAD DE UTILIZAR LAS CLASES ANTIGUAS Vector, Hashtable y Stack.