Conjunto de hash de Java La clase implementa la interfaz Set, respaldada por una tabla hash que en realidad es una instancia de HashMap. No se ofrece ninguna garantía en cuanto al orden de iteración de los conjuntos hash, lo que significa que la clase no garantiza el orden constante de los elementos a lo largo del tiempo. Esta clase permite el elemento nulo. La clase también ofrece un rendimiento de tiempo constante para operaciones básicas como agregar, eliminar, contener y dimensionar, suponiendo que la función hash disperse los elementos adecuadamente entre los depósitos, lo que veremos más adelante en el artículo.
Características de Java HashSet
A continuación se mencionan algunas características importantes de HashSet:
- Implementos Establecer interfaz .
- La estructura de datos subyacente para HashSet es Tabla de picadillo .
- Como implementa Set Interface, no se permiten valores duplicados.
- No se garantiza que los objetos que inserte en HashSet se inserten en el mismo orden. Los objetos se insertan según su código hash.
- Se permiten elementos NULL en HashSet.
- HashSet también implementa Serializable y Clonable interfaces.
Declaración de HashSet
public class HashSet extends AbstractSet implements Set, Cloneable, Serializable>
dónde Y es el tipo de elementos almacenados en un HashSet.
Ejemplo de HashSet en Java
Java
// Java program to illustrate the concept> // of Collection objects storage in a HashSet> import> java.io.*;> import> java.util.*;> > class> CollectionObjectStorage {> > >public> static> void> main(String[] args)> >{> >// Instantiate an object of HashSet> >HashSet set =>new> HashSet();> > >// create ArrayList list1> >ArrayList list1 =>new> ArrayList();> > >// create ArrayList list2> >ArrayList list2 =>new> ArrayList();> > >// Add elements using add method> >list1.add(>1>);> >list1.add(>2>);> >list2.add(>1>);> >list2.add(>2>);> >set.add(list1);> >set.add(list2);> > >// print the set size to understand the> >// internal storage of ArrayList in Set> >System.out.println(set.size());> >}> }> |
cómo abrir un archivo con java
>
>Producción:
1>
Antes de almacenar un objeto, HashSet verifica si existe una entrada utilizando los métodos hashCode() y equals(). En el ejemplo anterior, dos listas se consideran iguales si tienen los mismos elementos en el mismo orden. Cuando invocas el código hash() método en las dos listas, ambas darían el mismo hash ya que son iguales.
Nota: HashSet lo hace no almacenar artículos duplicados , si le das dos Objetos que son iguales, entonces almacena solo el primero, aquí está lista1.
La jerarquía de HashSet es la siguiente:
Funcionamiento interno de un HashSet
Todas las clases de la interfaz Set están respaldadas internamente por Map. HashSet usa HashMap para almacenar su objeto internamente. Debes preguntarte que para ingresar un valor en HashMap necesitamos un par clave-valor, pero en HashSet, solo pasamos un valor.
Almacenamiento en HashMap: En realidad, el valor que insertamos en HashSet actúa como una clave para el objeto del mapa y, para su valor, Java usa una variable constante. Entonces, en el par clave-valor, todos los valores serán iguales.
Implementación de HashSet en documento Java
private transient HashMap map; // Constructor - 1 // All the constructors are internally creating HashMap Object. public HashSet() { // Creating internally backing HashMap object map = new HashMap(); } // Constructor - 2 public HashSet(int initialCapacity) { // Creating internally backing HashMap object map = new HashMap(initialCapacity); } // Dummy value to associate with an Object in Map private static final Object PRESENT = new Object();> Si miramos el agregar() método de la clase HashSet:
public boolean add(E e) { return map.put(e, PRESENT) == null; }> Podemos notar que el método add() de la clase HashSet llama internamente al poner() método para respaldar el objeto HashMap pasando el elemento que ha especificado como clave y la constante PRESENTE como valor. eliminar() El método también funciona de la misma manera. Llama internamente al método remove de la interfaz Map.
public boolean remove(Object o) { return map.remove(o) == PRESENT; }> HashSet no solo almacena objetos únicos sino también una colección de objetos única como Lista de arreglo , Lista enlazada , Vector, etc.
Constructores de la clase HashSet
Para crear un HashSet, necesitamos crear un objeto de la clase HashSet. La clase HashSet consta de varios constructores que permiten la posible creación del HashSet. Los siguientes son los constructores disponibles en esta clase.
1. HashSet()
Este constructor se utiliza para construir un objeto HashSet vacío en el que la capacidad inicial predeterminada es 16 y el factor de carga predeterminado es 0,75. Si deseamos crear un HashSet vacío con el nombre hs, entonces se puede crear como:
HashSet hs = new HashSet();>
2. HashSet (int capacidad inicial)
Este constructor se utiliza para construir un objeto HashSet vacío en el que se especifica la capacidad inicial en el momento de la creación del objeto. Aquí, el factor de carga predeterminado sigue siendo 0,75.
HashSet hs = new HashSet(int initialCapacity);>
3. HashSet (int capacidad inicial, factor de carga flotante)
Este constructor se utiliza para construir un objeto HashSet vacío en el que la capacidad inicial y el factor de carga se especifican en el momento de la creación del objeto.
HashSet hs = new HashSet(int initialCapacity, float loadFactor);>
4. HashSet (Colección)
Este constructor se utiliza para construir un objeto HashSet que contiene todos los elementos de la colección dada. En resumen, este constructor se utiliza cuando se necesita alguna conversión de cualquier objeto Collection al objeto HashSet. Si deseamos crear un HashSet con el nombre hs, podemos crearlo como:
HashSet hs = new HashSet(Collection C);>
A continuación se muestra la implementación de los temas anteriores:
Java
// Java program to Demonstrate Working> // of HashSet Class> > // Importing required classes> import> java.util.*;> > // Main class> // HashSetDemo> class> GFG {> > >// Main driver method> >public> static> void> main(String[] args)> >{> > >// Creating an empty HashSet> >HashSet h =>new> HashSet();> > >// Adding elements into HashSet> >// using add() method> >h.add(>'India'>);> >h.add(>'Australia'>);> >h.add(>'South Africa'>);> > >// Adding duplicate elements> >h.add(>'India'>);> > >// Displaying the HashSet> >System.out.println(h);> >System.out.println(>'List contains India or not:'> >+ h.contains(>'India'>));> > >// Removing items from HashSet> >// using remove() method> >h.remove(>'Australia'>);> >System.out.println(>'List after removing Australia:'> >+ h);> > >// Display message> >System.out.println(>'Iterating over list:'>);> > >// Iterating over hashSet items> >Iterator i = h.iterator();> > >// Holds true till there is single element remaining> >while> (i.hasNext())> > >// Iterating over elements> >// using next() method> >System.out.println(i.next());> >}> }> |
>
>Producción:
[South Africa, Australia, India] List contains India or not:true List after removing Australia:[South Africa, India] Iterating over list: South Africa India>
Métodos en HashSet
| MÉTODO | DESCRIPCIÓN |
|---|---|
| agregar(Y y) | Se utiliza para agregar el elemento especificado si no está presente; si está presente, devuelve falso. |
| claro() | Se utiliza para eliminar todos los elementos del conjunto. |
| contiene(Objeto o) | Se utiliza para devolver verdadero si un elemento está presente en un conjunto. |
| eliminar (Objeto o) | Se utiliza para eliminar el elemento si está presente en el conjunto. |
| iterador() | Se utiliza para devolver un iterador sobre el elemento del conjunto. |
| esta vacio() | Se utiliza para comprobar si el conjunto está vacío o no. Devuelve verdadero para el conjunto vacío y falso para una condición no vacía. |
| tamaño() | Se utiliza para devolver el tamaño del conjunto. |
| clon() | Se utiliza para crear una copia superficial del conjunto. |
Realizar varias operaciones en HashSet
Veamos cómo realizar algunas operaciones de uso frecuente en HashSet.
1. Agregar elementos en HashSet
Para agregar un elemento al HashSet, podemos usar el método add(). Sin embargo, el orden de inserción no se conserva en HashSet. Debemos tener en cuenta que no se permiten elementos duplicados y que todos los elementos duplicados se ignoran.
Ejemplo
Java
// Java program to Adding Elements to HashSet> > // Importing required classes> import> java.io.*;> import> java.util.*;> > // Main class> // AddingElementsToHashSet> class> GFG {> > >// Method 1> >// Main driver method> >public> static> void> main(String[] args)> >{> >// Creating an empty HashSet of string entities> >HashSet hs =>new> HashSet();> > >// Adding elements using add() method> >hs.add(>'Geek'>);> >hs.add(>'For'>);> >hs.add(>'Geeks'>);> > >// Printing all string el=ntries inside the Set> >System.out.println(>'HashSet elements : '> + hs);> >}> }> |
>
>Producción:
HashSet elements : [Geek, For, Geeks]>
2. Eliminar elementos en HashSet
Los valores se pueden eliminar del HashSet utilizando el método remove().
Ejemplo
Java
// Java program Illustrating Removal Of Elements of HashSet> > // Importing required classes> import> java.io.*;> import> java.util.*;> > // Main class> // RemoveElementsOfHashSet> class> GFG {> > >// Main driver method> >public> static> void> main(String[] args)> >{> >// Creating an> >HashSet hs =>new> HashSet();> > >// Adding elements to above Set> >// using add() method> >hs.add(>'Geek'>);> >hs.add(>'For'>);> >hs.add(>'Geeks'>);> >hs.add(>'A'>);> >hs.add(>'B'>);> >hs.add(>'Z'>);> > >// Printing the elements of HashSet elements> >System.out.println(>'Initial HashSet '> + hs);> > >// Removing the element B> >hs.remove(>'B'>);> > >// Printing the updated HashSet elements> >System.out.println(>'After removing element '> + hs);> > >// Returns false if the element is not present> >System.out.println(>'Element AC exists in the Set : '> >+ hs.remove(>'AC'>));> >}> }> |
>
>Producción:
Initial HashSet [A, B, Geek, For, Geeks, Z] After removing element [A, Geek, For, Geeks, Z] Element AC exists in the Set : false>
3. Iterando a través del HashSet
Itere a través de los elementos de HashSet utilizando el método iterator(). Además, el más famoso es utilizar el mejorado para bucle.
Ejemplo
bloque de código
ProducciónA, B, Geek, For, Geeks, Z, A, B, Geek, For, Geeks, Z,>
Complejidad temporal de las operaciones HashSet: La estructura de datos subyacente de HashSet es hashtable. Por lo tanto, se requiere amortizar la complejidad del tiempo (caso promedio o habitual) para agregar, eliminar y buscar (contiene el método) de HashSet. O(1) tiempo.
Rendimiento de HashSet
HashSet extiende la clase Abstract Set e implementa Colocar , Clonable y Serializable interfaces donde E es el tipo de elementos mantenidos por este conjunto. La subclase directamente conocida de HashSet es LinkedHashSet.
Ahora, para mantener un rendimiento de tiempo constante, iterar sobre HashSet requiere un tiempo proporcional a la suma del tamaño de la instancia de HashSet (la cantidad de elementos) más la capacidad de la instancia de HashMap de respaldo (la cantidad de depósitos). Por lo tanto, es muy importante no establecer la capacidad inicial demasiado alta (o el factor de carga demasiado bajo) si el rendimiento de la iteración es importante.
- Capacidad inicial: La capacidad inicial significa la cantidad de depósitos cuando se crea la tabla hash (HashSet utiliza internamente la estructura de datos de la tabla hash). La cantidad de depósitos aumentará automáticamente si el tamaño actual se llena.
- Factor de carga: El factor de carga es una medida de qué tan lleno se permite que esté el HashSet antes de que su capacidad aumente automáticamente. Cuando el número de entradas en la tabla hash excede el producto del factor de carga y la capacidad actual, la tabla hash se repite (es decir, se reconstruyen las estructuras de datos internas) para que la tabla hash tenga aproximadamente el doble de depósitos.
Number of stored elements in the table Load Factor = ----------------------------------------- Size of the hash table>
Ejemplo: Si la capacidad interna es 16 y el factor de carga es 0,75, entonces la cantidad de cubos aumentará automáticamente cuando la mesa tenga 12 elementos.
Efecto sobre el rendimiento:
El factor de carga y la capacidad inicial son dos factores principales que afectan el rendimiento de las operaciones de HashSet. Un factor de carga de 0,75 proporciona un rendimiento muy eficaz con respecto a la complejidad temporal y espacial. Si aumentamos el valor del factor de carga más que eso, entonces se reducirá la sobrecarga de memoria (porque disminuirá la operación de reconstrucción interna), pero afectará la operación de agregar y buscar en la tabla hash. Para reducir la operación de repetición debemos elegir sabiamente la capacidad inicial. Si la capacidad inicial es mayor que el número máximo de entradas dividido por el factor de carga, nunca se producirá ninguna operación de repetición.
Nota: La implementación en un HashSet no está sincronizada, en el sentido de que si varios subprocesos acceden a un conjunto de hash al mismo tiempo y al menos uno de los subprocesos modifica el conjunto, debe sincronizarse externamente. Por lo general, esto se logra mediante la sincronización de algún objeto que encapsule naturalmente el conjunto. Si no existe tal objeto, el conjunto debe empaquetarse utilizando el método Collections.synchronizedSet. Es mejor hacerlo en el momento de la creación, para evitar el acceso accidental y no sincronizado al conjunto, como se muestra a continuación:
Establecer s = Collections.synchronizedSet(new HashSet(…));
Métodos utilizados con HashSet
1. Métodos heredados de la clase java.util.AbstractSet
| Método cadena en matriz en c | Descripción |
|---|---|
| es igual() | Se utiliza para verificar la igualdad de un Objeto con un HashSet y compararlos. La lista devuelve verdadero solo si ambos HashSet contienen los mismos elementos, independientemente del orden. |
| código hash() | Devuelve el valor del código hash para este conjunto. |
| eliminarTodo(colección) | Este método se utiliza para eliminar todos los elementos de la colección que están presentes en el conjunto. Este método devuelve verdadero si este conjunto cambia como resultado de la llamada. |
2. Métodos heredados de la clase java.util.AbstractCollection
| MÉTODO | DESCRIPCIÓN |
|---|---|
| agregar todo (colección) | Este método se utiliza para agregar todos los elementos de la colección mencionada al conjunto existente. Los elementos se añaden aleatoriamente sin seguir ningún orden específico. |
| contieneTodo(colección) | Este método se utiliza para comprobar si el conjunto contiene todos los elementos presentes en la colección dada o no. Este método devuelve verdadero si el conjunto contiene todos los elementos y devuelve falso si falta alguno de los elementos. |
| retenerTodo(colección) | Este método se utiliza para conservar todos los elementos del conjunto que se mencionan en la colección dada. Este método devuelve verdadero si este conjunto cambió como resultado de la llamada. |
| a matriz() | Este método se utiliza para formar una matriz de los mismos elementos que la del Conjunto. |
| Encadenar() | El método toString() de Java HashSet se utiliza para devolver una representación de cadena de los elementos de la colección HashSet. |
3. Métodos declarados en la interfaz java.util.Collection
| MÉTODO | DESCRIPCIÓN |
|---|---|
| corriente paralela() | Devuelve un Stream posiblemente paralelo con esta colección como fuente. |
| removeIf?(Filtro de predicado) | Elimina todos los elementos de esta colección que satisfacen el predicado dado. |
| arroyo() | Devuelve un Stream secuencial con esta colección como origen. |
| toArray? (generador de funciones internas) | Devuelve una matriz que contiene todos los elementos de esta colección, utilizando la función generadora proporcionada para asignar la matriz devuelta. |
4. Métodos declarados en la interfaz java.lang.Iterable
| MÉTODO | DESCRIPCIÓN |
|---|---|
| ¿Para cada uno? (Acción del consumidor) | Realiza la acción dada para cada elemento del Iterable hasta que se hayan procesado todos los elementos o la acción genere una excepción. |
5. Métodos declarados en la interfaz java.util.Set
| MÉTODO | DESCRIPCIÓN |
|---|---|
| ¿Agregar todo? (Colección c) | Agrega todos los elementos de la colección especificada a este conjunto si aún no están presentes (operación opcional). |
| ¿Contiene todo? (Colección c) | Devuelve verdadero si este conjunto contiene todos los elementos de la colección especificada. |
| ¿es igual a?(Objeto o) | Compara el objeto especificado con este conjunto para determinar la igualdad. |
| código hash() | Devuelve el valor del código hash para este conjunto. |
| ¿eliminar todo? (Colección c) | Elimina de este conjunto todos los elementos contenidos en la colección especificada (operación opcional). |
| ¿retener todo? (Colección c) | Conserva solo los elementos de este conjunto que están contenidos en la colección especificada (operación opcional). |
| a matriz() | Devuelve una matriz que contiene todos los elementos de este conjunto. |
| aArray?(T[]a) | Devuelve una matriz que contiene todos los elementos de este conjunto; el tipo de tiempo de ejecución de la matriz devuelta es el de la matriz especificada. |
Preguntas frecuentes sobre HashSet en Java
P1. ¿Qué es HashSet en Java?
Respuesta:
HashSet es un tipo de clase que extiende AbstractSet e implementa interfaces Set.
P2. ¿Por qué se utiliza HashSet?
Respuesta:
HashSet se utiliza para evitar datos duplicados y encontrar valor con el método rápido.
P3. Diferencias entre HashSet y HashMap.
Respuesta:
| Base | Conjunto de hash | HashMap |
|---|---|---|
| Implementación | HashSet implementa una interfaz Set. | HashMap implementa una interfaz storeMap. |
| Duplicados | HashSet no permite valores duplicados. | HashMap almacena los pares clave y valor y no permite claves duplicadas. Si la clave está duplicada, la clave anterior se reemplaza con el nuevo valor. |
| Número de objetos durante el almacenamiento de objetos. | HashSet requiere solo un objeto agregado (Objeto o). | HashMap requiere dos objetos colocados (tecla K, valor V) para agregar un elemento al objeto HashMap. |
| valor ficticio | HashSet usa internamente HashMap para agregar elementos. En HashSet, el argumento pasado en el método add(Object) sirve como clave K. Java asocia internamente un valor ficticio para cada valor pasado en el método add(Object). | HashMap no tiene ningún concepto de valor ficticio. |
| Almacenar o agregar un mecanismo | HashSet utiliza internamente el objeto HashMap para almacenar o agregar los objetos. | HashMap utiliza internamente hash para almacenar o agregar objetos |
| Más rápido | HashSet es más lento que HashMap. | HashMap es más rápido que HashSet. |
| Inserción | HashSet utiliza el método add() para agregar o almacenar datos. | HashMap utiliza el método put() para almacenar datos. |
| Ejemplo | HashSet es un conjunto, p.e. {1, 2, 3, 4, 5, 6, 7}. | HashMap es un mapa de par clave -> valor (clave a valor), p. {a -> 1, b -> 2, c -> 2, d -> 1}. |
P4. Diferencias entre HashSet y TreeSet en Java.
Respuesta:
| Base | Conjunto de hash | Conjunto de árboles |
|---|---|---|
| Velocidad e implementación interna de la acción de lanzamiento. | Para operaciones como buscar, insertar y eliminar. En promedio, estas operaciones requieren un tiempo constante. HashSet es más rápido que TreeSet. HashSet se implementa mediante una tabla hash. | TreeSet toma O (Log n) para buscar, insertar y eliminar, que es superior a HashSet. Pero TreeSet mantiene los datos ordenados. Además, admite operaciones como mayor () (devuelve el elemento menos alto), piso (), techo (), etc. Estas operaciones también son O (Log n) en TreeSet y no se admiten en HashSet. TreeSet se implementa utilizando un árbol de búsqueda binaria autoequilibrado (árbol rojo-negro). TreeSet está respaldado por TreeMap en Java. |
| Realizar pedidos | Los elementos de HashSet no están ordenados. | TreeSet mantiene los objetos en orden definido por el método Comparable o Comparator en Java. Los elementos de TreeSet se ordenan en orden ascendente de forma predeterminada. Ofrece varios métodos para tratar el conjunto ordenado como first(), last(), headSet(), tailSet(), etc. |
| Objeto nulo | HashSet permite el objeto nulo. | TreeSet no permite objetos nulos y arroja NullPointerException. Por qué, es porque TreeSet usa el método compareTo() para comparar claves, y compareTo() arrojará java.lang.NullPointerException. |
| Comparación | HashSet utiliza el método equals() para comparar dos objetos en el Conjunto y detectar duplicados. | TreeSet usa el método compareTo() para el mismo propósito. Si equals() y compareTo() no son consistentes, es decir, para dos objetos iguales, iguales deben devolver verdadero mientras que compareTo() debe devolver cero, entonces romperá el contrato de la interfaz Set y permitirá duplicados en implementaciones de Set como TreeSet |