Clases de Colecciones en Java
Marco de Colecciones en Java Las colecciones en Java se pueden dividir aproximadamente en tres sistemas principales: Set, List y Map. Set representa colecciones desordenadas e no duplicadas; List representa coleccciones ordenadas y con elementos duplicados; mientras que Map representa colecciones con relaciones de mapeo. Desde Java 5, se añadió el sistema de colecciones Queue, que representa una implementación de colección tipo cola.
Las clases de colección de Java se derivan principalmente de dos interfaces: Collection y Map. Estas dos interfaces son las raíces del marco de colecciones de Java y contienen subinterfaces o clases de implementación. El árbol de herencia de las interfaces y clases de implementación de Collection y Map se muestra a continuación. Entre las colecciones Set, List, Queue y Map, las más utilizadas son HashSet, TreeSet, ArrayList, ArrayDeque, LinkedList, HashMap y TreeMap.
Interfaces Collection e Iterator
- Interface Collection La interfaz Collection es la interfaz padre de las interfaces List, Set y Queue. Los métodos definidos en esta interfaz pueden utilizarse tanto para colecciones Set como para operaciones en colecciones List y Queue. Los métodos definidos en la interfaz Collection se pueden ver en la documentación de la API de Java.
import java.util.*;
public class EjemploColeccion {
public static void main(String[] args) {
Coleccion datos = new ArrayLista();
// Aunque las colecciones no pueden contener valores de tipos primitivos, Java soporta autoboxing
// Sobre autoboxing, ver http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html
// Agregar elementos
datos.agregar("Wukong");
datos.agregar(6);
System.out.println("Número de elementos en datos: " + datos.tamano());
// Eliminar elemento específico
datos.eliminar(6);
System.out.println("Número de elementos en datos: " + datos.tamano());
// Verificar si contiene una cadena específica
System.out.println("¿Contiene datos la cadena \"Wukong\"? " + datos.contiene("Wukong"));
datos.agregar("Java");
System.out.println("Elementos de datos: " + datos);
Coleccion libros = new ConjuntoHash();
libros.agregar("Java");
libros.agregar("C++");
System.out.println("¿Contiene datos completamente a libros? " + datos.contieneTodos(libros));
// Restar elementos de libros de datos
datos.eliminarTodos(libros);
System.out.println("Elementos de datos: " + datos);
// Eliminar todos los elementos de datos
datos.limpiar();
System.out.println("Elementos de datos: " + datos);
System.out.println("Elementos de libros: " + libros);
// libros solo contiene elementos que también están en datos
libros.mantenerTodos(datos);
System.out.println("Elementos de libros: " + libros);
}
}
- Interface Iterator Iterator se utiliza principalmente para recorrer los elementos de una colección Collection. El objeto Iterator se denomina iterador. La interfaz Iterator define los siguientes tres métodos:
import java.util.*;
public class EjemploIterador {
public static void main(String[] args) {
// Crear colección
Coleccion libros = new ConjuntoHash();
libros.agregar("Java");
libros.agregar("C++");
libros.agregar("JavaScript");
// Obtener iterador para la colección libros
Iterador iterador = libros.iterador();
while(iterador.tieneSiguiente()) {
// El método iterador.siguiente() devuelve un tipo Object
// Se necesita conversión de tipo
String libro = (String)iterador.siguiente();
System.out.println(libro);
if(libro.equals("Java")) {
// Eliminar el elemento devuelto por el método anterior siguiente()
iterador.eliminar();
}
}
// Imprimir colección
System.out.println(libros);
}
}
Nota: al utilizar Iterator para acceder a los elementos de la colección Collection, los elementos de la colección no pueden ser modificados. Solo se puede eliminar el elemento de la colección devuelto por el método anterior next() a través del método remove() del Iterator; de lo contrario, se lanzará una excepción java.util.ConcurrentModificationException.
- Uso del bucle foreach para recorrer elementos de colección Además de utilizar la interfaz Iterator para acceder a los elementos de la colección Collection, el bucle foreach es más conveniente para recorrer elementos.
import java.util.*;
public class EjemploForeach {
public static void main(String[] args) {
// Crear colección
Coleccion libros = new ConjuntoHash();
libros.agregar("C++");
libros.agregar("Java");
libros.agregar("JavaScript");
// Recorrer con bucle foreach
for (Object obj : libros) {
String libro = (String)obj;
System.out.println(libro);
}
}
}
Nota: al utilizar el bucle foreach para acceder a los elementos de la colección, la colección tampoco puede ser modificada; de lo contrario, se lanzará una excepción ConcurrentModificationException.
Conjuntos Set Los conjuntos Set no permiten contener elementos duplicados. Set determina si dos objetos son iguales no utilizando el operador ==, sino mediante el método equals. Esto significa que si dos objetos devuelven true al compararse con el método equals, Set no aceptará estos dos objetos; por el contrario, si dos objetos devuelven false al compararse con el método equals, Set aceptará estos objetos.
import java.util.*;
public class EjemploSet {
public static void main(String[] args) {
// Crear conjunto
Set datos = new ConjuntoHash();
// Agregar
datos.agregar(new String("Java"));
// Los dos objetos de cadena agregados al conjunto claramente no son el mismo objeto
// (porque se llamó a new dos veces para crear cadenas)
// Estos dos strings devolverán al comparar con ==, pero mediante equals devuelven true, por lo que la adición falla
boolean resultado = datos.agregar(new String("Java"));
// El conjunto solo tiene un elemento
System.out.println(resultado + "--->" + datos);
}
}
- Conjunto HashSet Características de HashSet:
- No puede garantizar el orden de los elementos, el orden puede cambiar;
- HashSet no es sincronizado, si varios hilos acceden a HashSet simultáneamente, debe garantizar su sincronización mediante código;
- Los elementos de la colección pueden ser null.
Estándar para determinar elementos iguales en HashSet: Al almacenar un elemento en un HashSet, HashSet llama al método hashCode() del objeto para obtener su valor HashCode y luego, según este valor, decide la posición de almacenamiento del objeto en HashSet. Si dos elementos comparados con el método equals() devuelven true, pero sus métodos hashCode() devuelven valores diferentes, HashSet los almacenará en diferentes posiciones y aún así se puede agregar correctamente.
import java.util.*;
public class EjemploHashSet {
public static void main(String[] args) {
HashSet datos = new HashSet();
datos.agregar(new ClaseA());
datos.agregar(new ClaseA());
datos.agregar(new ClaseB());
datos.agregar(new ClaseB());
datos.agregar(new ClaseC());
datos.agregar(new ClaseC());
System.out.println(datos);
}
}
// ClaseA sobrescribe equals pero no hashCode
class ClaseA {
public boolean equals(Object obj) {
return true;
}
}
// ClaseB sobrescribe hashCode pero no equals
class ClaseB {
public int hashCode() {
return 1;
}
}
// ClaseC sobrescribe equals y hashCode
class ClaseC {
public boolean equals(Object obj) {
return true;
}
public int hashCode() {
return 2;
}
}
- Conjunto LinkedHashSet LinkedHashSet utiliza una lista enlazada para mantener el orden de los elementos, lo que hace que los elementos parezcan guardados en el orden de inserción. LinkedHashSet necesita mantener el orden de inserción de los elementos, por lo que su rendimiento es menor que HashSet, pero al acceder a todos los elementos del Set, tendrá un buen rendimiento porque mantiene el orden internamente mediante una lista enlazada.
import java.util.*;
public class EjemploLinkedHashSet {
public static void main(String[] args) {
// Crear conjunto
LinkedHashSet datos = new LinkedHashSet();
datos.agregar("Java");
datos.agregar("C++");
System.out.println(datos);
datos.eliminar("Java");
datos.agregar("Java");
System.out.println(datos);
}
}
- Conjunto TreeSet TreeSet puede garantizar que los elementos de la colección estén en estado ordenado. A diferencia de HashSet, que utiliza un algoritmo hash para decidir la posición de almacenamiento de los elementos, TreeSet utiliza una estructura de datos de árbol rojo-negro para almacenar los elementos de la colección.
import java.util.*;
public class EjemploTreeSet {
public static void main(String[] args) {
// Crear conjunto
TreeSet numeros = new TreeSet();
numeros.agregar(5);
numeros.agregar(2);
numeros.agregar(10);
numeros.agregar(-9);
// Imprimir elementos del conjunto
System.out.println(numeros);
// Imprimir primer elemento
System.out.println(numeros.primero());
// Imprimir último elemento
System.out.println(numeros.ultimo());
// Devolver subconjunto menor que 4, sin incluir 4
System.out.println(numeros.cabezaConjunto(4));
// Devolver subconjunto mayor que 5, si el conjunto contiene 5, el subconjunto también contiene 5
System.out.println(numeros.colaConjunto(5));
// Devolver subconjunto mayor o igual que -3 y menor que 4
System.out.println(numeros.subConjunto(-3, 4));
}
}
TreeSet soporta dos métodos de ordenación: ordenación natural y ordenación personalizada. Por defecto, TreeSet utiliza la ordenación natural.
Ordenación natural TreeSet llamará al método compareTo(Object obj) de los elementos de la colección para comparar el tamaño entre los elementos y luego ordenará los elementos de la colección en orden ascendente; este método es la ordenación natural. Cuando un objeto llama a este método para compararse con otro objeto, por ejemplo obj1.compareTo(obj2), si este método devuelve 0, indica que estos dos objetos son iguales; si devuelve un entero positivo, indica que obj1 es mayor que obj2; si devuelve un entero negativo, indica que obj1 es menor que obj2.
Si se agregan objetos de clases personalizadas a TreeSet, la premisa es que la clase personalizada del usuario implementa la interfaz Comparable; para la colección TreeSet, el único criterio para determinar si dos objetos son iguales es: dos objetos comparados mediante el método compareTo(Object obj) devuelven 0; si devuelven 0, se consideran iguales; de lo contrario, se consideran diferentes.
Ordenación personalizada Si se necesita implementar una ordenación personalizada, como ordenación descendiente, se puede ayudar mediante la interfaz Comparator. Esta interfaz contiene un método int compare(T o1, T o2) que se utiliza para comparar el tamaño de o1 y o2; si devuelve un entero positivo, o1 es mayor que o2; si devuelve 0, o1 es igual a o2; si devuelve un entero negativo, o1 es menor que o2.
import java.util.*;
public class EjemploTreeSetPersonalizado {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparador() {
// Ordenación personalizada
public int comparar(Object obj1, Object obj2) {
M m1 = (M)obj1;
M m2 = (M)obj2;
return m1.edad > m2.edad ? -1 :
m1.edad < m2.edad ? 1 :0;
}
});
ts.agregar(new M(5));
ts.agregar(new M(-3));
ts.agregar(new M(9));
System.out.println(ts);
}
}
class M {
int edad;
public M(int edad) {
this.edad = edad;
}
public String toString() {
return "M[edad:" + edad + "]";
}
}
- Conjunto EnumSet EnumSet es una clase de colección diseñada específicamente para clases de enumeración. Todos los elementos en EnumSet deben ser valores de enumeración de un tipo de enumeración específico, que se especifica explícita o implícitamente al crear EnumSet. Los elementos de la colección EnumSet también están ordenados, y EnumSet decide el orden de los elementos según el orden de definición de los valores de enumeración en la clase Enum.
import java.util.*;
public class EjemploEnumSet {
public static void main(String[] args) {
// Crear un EnumSet, los elementos son todos los valores de enumeración de la clase Estación
EnumSet es1 = EnumSet.todosDe(Estacion.class);
System.out.println(es1);
// Crear un EnumSet vacío, especificar que sus elementos son valores de enumeración de la clase Estación
EnumSet es2 = EnumSet.ningunoDe(Estacion.class);
System.out.println(es2);
// Agregar elementos
es2.agregar(Estacion.INVIERNO);
es2.agregar(Estacion.PRIMAVERA);
System.out.println(es2);
// Crear un EnumSet con valores de enumeración específicos
EnumSet es3 = EnumSet.de(Estacion.VERANO, Estacion.INVIERNO);
System.out.println(es3);
// Crear un EnumSet con un rango de valores de enumeración
EnumSet es4 = EnumSet.rango(Estacion.VERANO, Estacion.INVIERNO);
System.out.println(es4);
// es5 + es4 = todos los valores de enumeración de la clase Estación
EnumSet es5 = EnumSet.complementoDe(es4);
System.out.println(es5);
}
}
enum Estacion {
PRIMAVERA, VERANO, OTOÑO, INVIERNO
}
Colecciones List Como subinterfaz de Collection, la interfaz List puede utilizar todos los métodos de la interfaz Collection. Además, como List es una colección ordenada, List agrega algunos métodos para operar elementos de la colección según el índice.
import java.util.*;
public class EjemploLista {
public static void main(String[] args) {
// Crear objeto colección
Lista libros = new ArrayLista();
// Agregar
libros.agregar("Java");
libros.agregar("C++");
libros.agregar("JavaScript");
System.out.println(libros);
// Insertar nueva cadena en la segunda posición
libros.agregar(1, new String("Ajax"));
for(int i=0; i<libros.tamano(); i++) {
System.out.println(libros.obtener(i));
}
// Eliminar tercer elemento
libros.eliminar(2);
System.out.println(libros);
// Determinar la posición del elemento especificado en la Lista
System.out.println(libros.indiceDe(new String("Ajax")));
// Reemplazar el segundo elemento con una nueva cadena
libros.establecer(1, new String("PHP"));
System.out.println(libros);
// Subcolección desde el segundo elemento (incluido) hasta el tercero (excluido)
System.out.println(libros.subLista(1, 2));
}
}
- Interfaz ListIterator Además de proporcionar la interfaz Iterator, la colección List también proporciona la interfaz ListIterator. La interfaz ListIterator agrega los siguientes métodos sobre la base de la interfaz Iterator:
import java.util.*;
public class EjemploListIterator {
public static void main(String[] args) {
String[] libros = {"Java", "C++"};
Lista listaLibros = new ArrayLista();
for(int i=0; i<libros.length; i++) {
listaLibros.agregar(libros[i]);
}
// Interfaz ListIterator
IteradorLista lit = listaLibros.iteradorLista();
while(lit.tieneSiguiente()) {
System.out.println(lit.siguiente());
lit.agregar("------Separador------");
}
System.out.println("======Iteración inversa======");
while(lit.tieneAnterior()) {
System.out.println(lit.anterior());
}
}
}
- Clases de implementación ArrayList y Vector ArrayList y Vector se utilizan de manera casi idéntica, pero hay una diferencia significativa: ArrayList no es seguro para hilos; cuando varios hilos acceden a la misma colección ArrayList, si más de un hilo modifica la colección ArrayList, el programa debe garantizar manualmente la sincronización de la colección; pero la colección Vector es segura para hilos. Debido a que Vector es seguro para hilos, su rendimiento es menor que el de ArrayList. De hecho, incluso si se necesita garantizar la seguridad de hilos de la colección List, tampoco se recomienda usar la clase de implementación Vector. Más adelante se介绍ará una clase de utilidad Collections que puede convertir un ArrayList en uno seguro para hilos.
Vector también proporciona una subclase Stack para simular la estructura de datos de pila, proporcionando los siguientes métodos:
import java.util.*;
public class EjemploVector {
public static void main(String[] args) {
Pila pila = new Pila();
pila.empujar("Java");
pila.empujar("C++");
pila.empujar("PHP");
System.out.println(pila);
System.out.println(pila.mirar());
System.out.println(pila);
System.out.println(pila.sacar());
System.out.println(pila);
}
}
Colecciones Queue
- Clase de implementación PriorityQueue PriorityQueue no mantiene el orden de los elementos de la cola según el ordan en que se agregaron, sino que los reordena según el tamaño de los elementos. Por lo tanto, cuando se llama a los métodos peek() o poll() para extraer elementos de la cola, no se extrae el elemento que entró primero en la cola, sino el elemento más pequeño de la cola.
import java.util.*;
public class EjemploPriorityQueue {
public static void main(String[] args) {
PriorityQueue pq = new PriorityQueue();
// Agregar
pq.ofrecer(6);
pq.ofrecer(-3);
pq.ofrecer(9);
pq.ofrecer(0);
// Imprimir
System.out.println(pq);
// Acceder al primer elemento
System.out.println(pq.mirar());
}
}
PriorityQueue no permite insertar elementos null, ya que necesita ordenar los elementos de la cola. PriorityQueue tiene dos métodos de ordenación para los elementos: ordenación natural y ordenación personalizada. Los requisitos de PriorityQueue para los elementos son básicamente los mismos que TreeSet, por lo que el uso de ordenación natural y ordenación personalizado se puede consultar en TreeSet.
- Interfaz Deque y clase de implementación ArrayDeque La interfaz Deque es una subinterfaz de la interfaz Queue, representa una cola de doble extremo. La interfaz Deque define métodos que permiten operar elementos de la cola desde ambos extremos. Además, Deque no solo puede usarse como cola de doble extremo, sino que también puede usarse como pila, por lo que cuando se necesita usar una estructura de datos de pila, se recomienda usar ArrayDeque o LinkedList en lugar de Stack.
import java.util.*;
/**
* Usar ArrayDeque como pila
*/
public class EjemploArrayDeque {
public static void main(String[] args) {
ArrayDeque pila = new ArrayDeque();
// Empujar elementos en la pila
pila.empujar("Java");
pila.empujar("C++");
pila.empujar("PHP");
// Imprimir
System.out.println(pila);
// Acceder al primer elemento
System.out.println(pila.mirar());
System.out.println(pila);
// Sacar el primer elemento
System.out.println(pila.sacar());
System.out.println(pila);
}
}
- Clase de implementación LinkedList La clase LinkedList es una implementación de la interfaz List, lo que significa que es una colección List y se puede acceder aleatoriamente a los elementos de la colección según el índice. Además, LinkedList implementa la interfaz Deque, por lo que puede usarse como cola de doble extremo, y naturalmente también puede usarse como pila.
import java.util.*;
public class EjemploLinkedList {
public static void main(String[] args) {
LinkedList libros = new LinkedList();
// Agregar cadena al final de la cola
libros.ofrecer("Java");
// Agregar cadena a la parte superior de la pila
libros.empujar("C++");
// Agregar cadena al principio de la cola
libros.ofrecerPrimero("PHP");
// Imprimir
for(int i=0; i<libros.tamano(); i++) {
System.out.println(libros.obtener(i));
}
// Acceder sin eliminar el elemento superior de la pila
System.out.println(libros.mirarPrimero());
// Acceder sin eliminar el último elemento de la cola
System.out.println(libros.mirarUltimo());
// Sacar el elemento superior de la pila
System.out.println(libros.sacar());
// Imprimir
System.out.println(libros);
// Acceder y eliminar el último elemento de la cola
System.out.println(libros.sacarUltimo());
// Imprimir
System.out.println(libros);
}
}
Colecciones Map Map se utiliza para guardar datos con relaciones de mapeo, por lo que la colección Map guarda dos grupos de valores, un grupo guarda las claves (key) en Map, y el otro grupo guarda los valores (value) en Map. Existe una relación uno a uno unidireccional entre key y value, es decir, a través de una key específica, siempre se puede encontrar el value único y determinado correspondiente.
- Clases de implementación HashMap y Hashtable HashMap y Hashtable tienen dos diferencias significativas:
- Hashtable es una implementación de Map segura para hilos, pero HashMap no es segura para hilos, por lo que HashMap tiene un rendimiento ligeramente mayor que Hashtable.
- Hashtable no permite usar null como key o value, pero HashMap puede usar null como key o value.
HashMap y Hashtable determinan si dos keys son iguales mediante: dos keys comparadas con el método equals() devuelven true, y los valores hashCode de las two keys también son iguales.
HashMap y Hashtable determinan si two values son iguales mediante: dos objetos comparados con el método equals() devuelven true.
import java.util.*;
public class EjemploHashtable {
public static void main(String[] args) {
Hashtable ht = new Hashtable();
ht.poner(new ClaseX(60000), "Java");
ht.poner(new ClaseX(87563), "C++");
ht.poner(new ClaseX(1232), new ClaseY());
System.out.println(ht);
// Siempre que dos objetos comparados con el método equals() devuelvan true
// Hashtable considera que son values iguales
// Como Hashtable tiene un objeto B
// Comparado con cualquier objeto mediante equals() devuelve true, por lo que la siguiente salida es true
System.out.println(ht.contieneValor("Cadena de prueba"));
// Siempre que dos objetos de ClaseX tengan el mismo count, comparados con equals() devuelvan true, y los valores hashCode sean iguales
// Hashtable considera que son keys iguales, por lo que la salida es true
System.out.println(ht.contieneClave(new ClaseX(87563)));
// Eliminar par clave-valor
ht.eliminar(new ClaseX(1232));
// Obtener el Set compuesto por todas las keys de Hashtable
// De esta manera recorrer cada par clave-valor de Hashtable
for(Object key : llavesDe(ht) ) {
System.out.print(key + "------>");
System.out.println(ht.obtener(key));
}
}
}
class ClaseX {
int contador;
public ClaseX(int contador) {
this.contador = contador;
}
public boolean equals(Object obj) {
if(obj == this) {
return true;
}
if(obj != null && obj.getClass() == ClaseX.class) {
ClaseX a = (ClaseX)obj;
return (this.contador == a.contador);
}
return false;
}
public int hashCode() {
return this.contador;
}
}
class ClaseY {
public boolean equals(Object obj) {
return true;
}
}
- Clase de implementación LinkedHashMap LinkedHashMap necesita mantener el orden de inserción de los elementos, por lo que su rendimiento es menor que el de HashMap; pero porque mantiene el orden internamente mediante una lista enlazada, tiene un buen rendimiento al acceder a todos los elementos de Map.
import java.util.*;
public class EjemploLinkedHashMap {
public static void main(String[] args) {
LinkedHashMap puntuaciones = new LinkedHashMap();
puntuaciones.poner("Lenguaje", 80);
puntuaciones.poner("Inglés", 82);
puntuaciones.poner("Matemáticas", 76);
// Recorrer pares clave-valor en puntuaciones
for(Object key : puntuaciones.llaves() ) {
System.out.println(key + "----->" + puntuaciones.obtener(key));
}
System.out.println("========================");
// Iterar pares clave-valor en puntuaciones
for(Iterador it=puntuaciones.llaves().iterador(); it.tieneSiguiente(); ) {
Object key = it.siguiente();
System.out.println(key+ "------>"+puntuaciones.obtener(key));
}
}
}
- Usar Properties para leer y escribir archivos de propiedades La clase Properties puede asociar objetos Map con archivos de propiedades, por lo que puede escribir pares clave-valor del objeto Map en archivos de propiedades, y también puede cargar "nombre de propiedad=valor de propiedad" de archivos de propiedades en el objeto Map.
import java.io.*;
import java.util.*;
public class EjemploProperties {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
// Agregar propiedades a Properties
props.establecerPropiedad("usuario", "admin");
props.establecerPropiedad("contrasena", "123456");
// Guardar pares clave-valor de Properties en el archivo a.ini
props.guardar(new FileOutputStream("a.ini"), "línea de comentario");
// Crear un nuevo objeto Properties
Properties props2 = new Properties();
props2.establecerPropiedad("genero", "masculino");
// Cargar pares clave-valor del archivo a.ini en props2
props2.cargar(new FileInputStream("a.ini"));
System.out.println(props2);
}
}
- Interfaz SortedMap y clase de implementación TreeMap Al igual que la interfaz Set deriva la subinterfaz SortedSet, que tiene una clase de implementación TreeSet, la interfaz Map también deriva una subinterfaz SortedMap, que tiene una clase de implementación TreeMap. Por lo tanto, se puede hacer referencia a SortedSet y TreeSet para obtener más información.
import java.util.*;
public class EjemploTreeMap {
public static void main(String[] args) {
TreeMap tm = new TreeMap();
tm.poner(new R(3), "Java");
tm.poner(new R(-5), "C++");
tm.poner(new R(9), "PHP");
System.out.println(tm);
// Devolver el primer par clave-valor
System.out.println(tm.entradaPrimera());
// Devolver la última clave
System.out.println(tm.claveUltima());
// Devolver la clave más pequeña que new R(2)
System.out.println(tm.claveMayor(new R(2)));
// Devolver el par clave-valor más grande que new R(2)
System.out.println(tm.entradaMenor(new R(2)));
// Devolver subTreeMap
System.out.println(tm.subMapa(new R(-5), new R(4)));
}
}
class R implements Comparable {
int contador;
public R(int contador) {
this.contador = contador;
}
public String toString() {
return "R[contador:" + contador + "]";
}
public boolean equals(Object obj) {
if(obj == this) {
return true;
}
if(obj != null && obj.getClass() == R.class) {
R r = (R)obj;
return (this.contador == r.contador);
}
return false;
}
public int compareTo(Object obj) {
R r = (R)obj;
return this.contador > r.contador ? 1 :
this.contador < r.contador ? -1 : 0;
}
}
- Clase de implementación WeakHashMap WeakHashMap es similar a su uso básico con HashMap. La diferencia entre WeakHashMap y HashMap es que HashMap mantiene una referencia fuerte al objeto real para la clave, pero WeakHashMap solo mantiene una referencia débil al objeto real para la clave.
- Clase de implementación IdentityHashMap La clase de implementación IdentityHashMap es básicamente similar a HashMap, la diferencia es que IdentityHashMap compara si dos claves son iguales utilizando el operador ==, mientras que HashMap utiliza el método equals().
import java.util.*;
public class EjemploIdentityHashMap {
public static void main(String[] args) {
IdentityHashMap ihm = new IdentityHashMap();
ihm.poner(new String("Lenguaje"), 89);
ihm.poner(new String("Lenguaje"), 89);
ihm.poner("Java", 93);
ihm.poner("Java", 98);
System.out.println(ihm);
}
}
- Clase de implementación EnumMap
import java.util.*;
public class EjemploEnumMap {
public static void main(String[] args) {
EnumMap en = new EnumMap(Estacion.class);
en.poner(Estacion.VERANO, "Verano");
en.poner(Estacion.PRIMAVERA, "Primavera");
System.out.println(en);
}
}
enum Estacion {
PRIMAVERA, VERANO, OTOÑO, INVIERNO
}
Clase de utilidad para operar colecciones: Collections Java proporciona una clase de utilidad para operar colecciones como Set, List y Map: Collections. Esta clase de utilidad proporciona una gran cantidad de métodos para ordenar, buscar y modificar elementos de la colección, y también proporciona métodos para establecer objetos de colección como inmutables y para implementar control de sincronización en objetos de colección.
- Ordenación Los métodos específicos se pueden ver en la documentación de la API de Java.
import java.util.*;
public class EjemploOrdenacion {
public static void main(String[] args) {
ArrayLista nums = new ArrayLista();
nums.agregar(2);
nums.agregar(-5);
nums.agregar(3);
nums.agregar(0);
System.out.println(nums);
// Invertir
Collections.invertir(nums);
System.out.println(nums);
// Ordenar
Collections.ordenar(nums);
System.out.println(nums);
// Mezclar aleatoriamente
Collections.mezclar(nums);
System.out.println(nums);
}
}
- Búsqueda y reemplazo Los métodos específicos se pueden ver en la documentación de la API de Java.
import java.util.*;
public class EjemploBusqueda {
public static void main(String[] args) {
ArrayLista nums = new ArrayLista();
nums.agregar(2);
nums.agregar(-5);
nums.agregar(3);
nums.agregar(0);
System.out.println(nums);
// Imprimir elementos máximo y mínimo
System.out.println(Collections.maximo(nums));
System.out.println(Collections.minimo(nums));
// Reemplazar 0 con 1
Collections.reemplazarTodos(nums, 0, 1);
System.out.println(nums);
// Devolver el número de veces que aparece -5
System.out.println(Collections.frecuencia(nums, -5));
// Búsqueda binaria de la posición de -5 en la colección
Collections.ordenar(nums);
System.out.println(nums);
System.out.println(Collections.busquedaBinaria(nums, -5));
}
}
- Control de sincronización La clase Collections proporciona múltiples métodos synchronizedXxx(), que pueden empaquetar la colección especificada en una colección sincronizada de hilos, resolviendo así el problema de seguridad de hilos cuando varios hilos acceden a la colección simultáneamente.
import java.util.*;
public class EjemploSincronizado {
public static void main(String[] args) {
// Crear versiones seguras para hilos de List, Set y Map
Lista lista = Collections.listaSincronizada(new ArrayLista());
Set conjunto = Collections.conjuntoSincronizado(new ConjuntoHash());
Map mapa = Collections.mapaSincronizado(new HashMapa());
}
}
- Establecer colecciones inmutables Collections proporciona los siguientes tres tipos de métodos para devolver una colección inmutable:
import java.util.*;
public class EjemploInmodificable {
public static void main(String[] args) {
// Crear un objeto List vacío e inmutable
Lista lista = Collections.listaVacia();
// Crear un objeto Set con un solo elemento e inmutable
Set conjunto = Collections.conjuntoSingleton("Java");
// Crear un objeto Map común
Map puntuaciones = new HashMapa();
puntuaciones.poner("Chino", 80);
puntuaciones.poner("Inglés", 90);
// Devolver la versión inmutable del objeto Map común
Map mapaInmodificable = Collections.mapaInmodificable(puntuaciones);
// Lo siguiente generará una excepción
lista.agregar("Prueba");
conjunto.agregar("Prueba");
mapaInmodificable.poner("Matemáticas", 100);
}
}