español - ¿Por qué java.util.Set no tiene get(índice int)?
set java ejemplo (18)
En realidad, esta es una pregunta recurrente cuando se escriben aplicaciones JavaEE que usan Mapeo Relacional de Objetos (por ejemplo, con Hibernate); y de todas las personas que respondieron aquí, Andreas Petersson es el único que entendió el problema real y le ofreció la respuesta correcta: ¡a Java le falta una lista única! (o también puede llamarlo OrderedSet o IndexedSet).
Maxwing mencionó este caso de uso (en el que necesita datos ordenados Y únicos) y sugirió el ajuste Sorted, pero esto no es lo que realmente necesitaba Marty Pitt.
Este "IndexedSet" NO es lo mismo que un SortedSet: en un SortedSet, los elementos se ordenan utilizando un Comparador (o utilizando su ordenamiento "natural").
Pero en cambio, está más cerca de un LinkedHashSet (que otros también sugirieron), o incluso más que de un (ArieListSet) (también inexistente), porque garantiza que los elementos se devuelven en el mismo orden en que se insertaron.
Pero el LinkedHashSet es una implementación, no una interfaz. Lo que se necesita es una interfaz IndexedSet (o ListSet, OrderedSet o UniqueList). Esto permitirá al programador especificar que necesita una colección de elementos que tienen un orden específico y sin duplicados, y luego crear una instancia con cualquier implementación (por ejemplo, una implementación proporcionada por Hibernate).
Dado que JDK es de código abierto, tal vez esta interfaz finalmente se incluya en Java 7 ...
Estoy seguro de que hay una buena razón, pero ¿podría alguien explicar por qué la interfaz java.util.Set
carece de get(int Index)
, o algún método get()
similar?
Parece que los conjuntos son geniales para poner cosas, pero no puedo encontrar una forma elegante de recuperar un solo elemento de él.
Si sé que quiero el primer elemento, puedo usar set.iterator().next()
, pero, de lo contrario, parece que tengo que convertirlo en una matriz para recuperar un elemento en un índice específico.
¿Cuáles son las formas adecuadas de recuperar datos de un conjunto? (aparte de usar un iterador)
Estoy seguro de que el hecho de que se haya excluido de la API significa que hay una buena razón para no hacer esto. ¿Podría alguien iluminarme?
EDITAR: Algunas respuestas extremadamente buenas aquí, y algunas diciendo "más contexto". El escenario específico era una prueba de dbUnit, donde podría afirmar razonablemente que el conjunto devuelto de una consulta tenía solo 1 elemento, y estaba tratando de acceder a ese elemento.
Sin embargo, la pregunta es más válida sin el escenario, ya que permanece más enfocada:
¿Cuál es la diferencia entre conjunto y lista ?
Gracias a todos por las fantásticas respuestas a continuación.
Es cierto, el elemento en Set no está ordenado, por definición de Set Collection. Así que no se puede acceder por un índice.
Pero, ¿por qué no tenemos un método get (objeto), no proporcionando el índice como parámetro, sino un objeto que es igual al que estamos buscando? De esta manera, podemos acceder a los datos del elemento dentro del Conjunto, solo al conocer sus atributos utilizados por el método igual.
Este tipo de pregunta conduce a cuándo debe usar un conjunto y cuándo debe usar una lista. Por lo general, el consejo es:
- Si necesita datos ordenados, use una lista
- Si necesita datos únicos, use un Set
- Si necesita ambos, use uno: un conjunto de selección de datos (para los datos ordenados por el comparador) o un Conjunto / conjunto de datos ordenados (para los datos solicitados por inserción). Desafortunadamente, la API de Java aún no tiene OrderedSet / UniqueList.
Un cuarto caso que aparece a menudo es que no necesita ninguno. En este caso ves que algunos programadores van con listas y otros con conjuntos. Personalmente, me parece muy dañino verlo como una lista sin ordenar, porque es realmente una bestia completamente diferente. A menos que necesite cosas como establecer la unicidad o establecer la igualdad, siempre favorece las listas.
Esto se debe a que Set solo garantiza la singularidad, pero no dice nada sobre el acceso óptimo o los patrones de uso. Es decir, un Conjunto puede ser una Lista o un Mapa, cada uno de los cuales tiene características de recuperación muy diferentes.
La única razón que se me ocurre para usar un índice numérico en un conjunto sería para la iteración. Para eso, usa
for(A a : set) {
visit(a);
}
La razón por la que la interfaz Set no tiene una llamada de tipo de índice de obtención o incluso algo más básico, como primero () o último (), es porque es una operación ambigua y, por lo tanto, una operación potencialmente peligrosa. Si un método devuelve un Conjunto, y usted llama, diga el primer método () en él, ¿cuál es el resultado esperado, dado que un Conjunto genérico no ofrece ninguna garantía en el pedido? El objeto resultante puede variar muy bien entre cada llamada del método, o puede que no, y le dé una sensación de seguridad falsa, hasta que la biblioteca que está usando cambie la implementación de la parte inferior y ahora encuentre que todo su código se rompe para ninguna razón en particular.
Las sugerencias sobre soluciones alternativas aquí enumeradas son buenas. Si necesita acceso indexado, use una lista. Tenga cuidado al usar iteradores o toArray con un conjunto genérico, porque a) no hay garantía en el pedido yb) no hay garantía de que el pedido no cambie con las invocaciones posteriores o con diferentes implementaciones subyacentes. Si necesitas algo intermedio, lo que quieres es un SortedSet o un LinkedHashSet.
// Desearía que la interfaz Set tuviera un elemento get-random.
Me encontré con situaciones en las que realmente quería un conjunto ordenado con acceso a través del índice (estoy de acuerdo con otros carteles que acceder a un conjunto no clasificado con un índice no tiene sentido). Un ejemplo sería un árbol en el que quisiera que los niños fueran ordenados y no se permitieran los niños duplicados.
Necesitaba el acceso a través del índice para mostrarlos y los atributos establecidos fueron útiles para eliminar de manera eficiente los duplicados.
Al no encontrar una colección adecuada en java.util o en las colecciones de google, me pareció sencillo implementarla yo mismo. La idea básica es envolver un SortedSet y crear una lista cuando se requiere acceso a través de un índice (y olvidar la lista cuando se cambia el SortedSet). Por supuesto, esto solo funciona de manera eficiente cuando se modifica el ajuste SortedSet y el acceso a la lista se separa durante la vida útil de la Colección. De lo contrario, se comporta como una lista que se ordena a menudo, es decir, demasiado lenta.
Con un gran número de niños, esto mejoró mucho el rendimiento en una lista que mantuve ordenada a través de Collections.sort.
No estoy seguro de si alguien lo ha explicado exactamente de esta manera, pero debe comprender lo siguiente:
No hay ningún "primer" elemento en un conjunto.
Porque, como han dicho otros, los sets no tienen orden. Un conjunto es un concepto matemático que específicamente no incluye ordenar.
Por supuesto, su computadora realmente no puede mantener una lista de cosas que no están ordenadas en la memoria. Tiene que haber algún ordenamiento. Internamente es una matriz o una lista enlazada o algo así. Pero realmente no sabes qué es y realmente no tiene un primer elemento; el elemento que sale "primero" sale de esa manera por casualidad, y puede que no sea el primero la próxima vez. Incluso si tomaste medidas para "garantizar" un primer elemento en particular, aún está saliendo por casualidad, porque por casualidad lo hiciste bien para una implementación particular de un Conjunto; una implementación diferente podría no funcionar así con lo que hiciste. Y, de hecho, es posible que no conozca la implementación que está utilizando tan bien como cree.
La gente se topa con este TODO. LA. HORA. Con sistemas RDBMS y no entiendo. Una consulta RDBMS devuelve un conjunto de registros. Este es el mismo tipo de conjunto de las matemáticas: una colección desordenada de elementos, solo en este caso los elementos son registros. El resultado de una consulta RDBMS no tiene ningún orden garantizado a menos que use la cláusula ORDER BY, pero todo el tiempo la gente asume que sí lo hace y luego se tropieza un día cuando la forma de sus datos o código cambia ligeramente y hace que el optimizador de consultas funcione. de otra manera y de repente los resultados no salen en el orden que esperan. Normalmente, estas son las personas que no prestaron atención en la clase de la base de datos (o al leer la documentación o los tutoriales) cuando se les explicó, por adelantado, que los resultados de la consulta no tienen un orden garantizado.
Para obtener el elemento en un conjunto, utilizo el siguiente:
public T getElement(Set<T> set, T element) {
T result = null;
if (set instanceof TreeSet<?>) {
T floor = ((TreeSet<T>) set).floor(element);
if (floor != null && floor.equals(element))
result = floor;
} else {
boolean found = false;
for (Iterator<T> it = set.iterator(); !found && it.hasNext();) {
if (true) {
T current = it.next();
if (current.equals(element)) {
result = current;
found = true;
}
}
}
}
return result;
}
Porque los conjuntos no tienen pedido. Algunas implementaciones lo hacen (particularmente aquellas que implementan la interfaz java.util.SortedSet
), pero eso no es una propiedad general de los conjuntos.
Si está tratando de usar conjuntos de esta manera, debería considerar usar una lista en su lugar.
Pruebe este Código como una opción alternativa para acceder a través de índices
import java.io.*;
import java.util.*;
class GFG {
public static void main (String[] args) {
HashSet <Integer> mySet=new HashSet<Integer>();
mySet.add(100);
mySet.add(100);
int n = mySet.size();
Integer arr[] = new Integer[n];
arr = mySet.toArray(arr);
System.out.println(arr[0]);
}
}
Esto imprimirá 100.
Puedes hacer una new ArrayList<T>(set).get(index)
Si no le importa el conjunto que se ordenará, puede interesarle echar un vistazo al proyecto de indexed-tree-map .
El TreeSet / TreeMap proporciona acceso a los elementos por índice u obteniendo el índice de un elemento. Y la implementación se basa en actualizar los pesos de los nodos en el árbol RB. Así que no hay iteración o copia de seguridad por una lista aquí.
Si va a hacer muchos accesos aleatorios por índice en un conjunto, puede obtener una vista de matriz de sus elementos:
Object[] arrayView = mySet.toArray();
//do whatever you need with arrayView[i]
Sin embargo, hay dos inconvenientes principales:
- No es eficiente en memoria, ya que se debe crear una matriz para todo el conjunto.
- Si se modifica el conjunto, la vista se vuelve obsoleta.
Solo agregando un punto que no fue mencionado en la respuesta de mmyers .
Si sé que quiero el primer elemento, puedo usar set.iterator (). Next (), pero, de lo contrario, parece que tengo que convertirlo en una matriz para recuperar un elemento en un índice específico.
¿Cuáles son las formas adecuadas de recuperar datos de un conjunto? (aparte de usar un iterador)
También debe familiarizarse con la interfaz SortedSet
(cuya implementación más común es TreeSet
).
Un SortedSet es un conjunto (es decir, los elementos son únicos) que se mantiene ordenado por el orden natural de los elementos o utilizando algún Comparator
. Puede acceder fácilmente a los primeros y últimos elementos utilizando los métodos first()
y last()
. A SortedSet
es útil de vez en cuando, cuando necesita mantener su colección sin duplicados y ordenada de cierta manera.
Editar : si necesita un conjunto cuyos elementos se mantienen en orden de inserción (como una lista), eche un vistazo a LinkedHashSet
.
Tenga en cuenta que solo se puede acceder a la estructura de datos básica a través del índice.
- Se puede acceder a la estructura de datos de la matriz a través del índice con
O(1)
complejidad de tiempo para lograr la operación deget(int index)
. - También se puede acceder a la estructura de datos de LinkedList a través del índice, pero con
O(n)
complejidad del tiempo para lograr la operación deget(int index)
.
En Java, ArrayList
se implementa utilizando la estructura de datos Array .
Si bien la estructura de datos del Conjunto generalmente se puede implementar a través de la estructura de datos HashTable / HashMap o BalancedTree , para detectar rápidamente si existe un elemento y agregar un elemento no existente, generalmente un conjunto bien implementado puede lograr O(1)
tiempo en que la complejidad contains
operación. En Java, HashSet
es la implementación utilizada más común de Set , se implementa llamando a la API de HashMap
, y HashMap
se implementa mediante un encadenamiento separado con listas vinculadas (una combinación de Array y LinkedList ).
Dado que Set puede implementarse a través de una estructura de datos diferente, no existe un método get(int index)
para ello.
faltan algunas estructuras de datos de las colecciones estándar de java.
Bolsa (como conjunto pero puede contener elementos varias veces)
UniqueList (lista ordenada, puede contener cada elemento solo una vez)
Parece que necesitarías una lista única en este caso.
Si necesita estructuras de datos flexibles, podría estar interesado en Google Collections.
java.util.Set
es una colección de artículos sin ordenar. No tiene ningún sentido si el conjunto tiene un get (int index), porque Set no tiene un índice y también solo puede adivinar el valor.
Si realmente quieres esto, codifica un método para obtener un elemento aleatorio de Set.