Estoy seguro de que hay una buena razón, pero ¿alguien podría explicar por qué java.util.Set
falta la interfaz get(int Index)
o algún get()
método similar ?
Parece que los conjuntos son geniales para poner cosas, pero no puedo encontrar una manera elegante de recuperar un solo elemento.
Si sé que quiero el primer elemento, puedo usarlo set.iterator().next()
, pero de lo contrario parece que tengo que enviarlo a una matriz para recuperar un elemento en un índice específico.
¿Cuáles son las formas apropiadas de recuperar datos de un conjunto? (aparte de usar un iterador)
Estoy seguro de que el hecho de que esté excluido de la API significa que hay una buena razón para no hacerlo: ¿podría alguien aclararme?
EDITAR: Algunas respuestas extremadamente buenas aquí, y algunas que dicen "más contexto". El escenario específico era una prueba dbUnit, donde razonablemente podía afirmar 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 set y list ?
Gracias a todos por las fantásticas respuestas a continuación.
fuente
Respuestas:
Porque los conjuntos no tienen orden. Algunas implementaciones sí (particularmente aquellas que implementan la
java.util.SortedSet
interfaz), pero esa 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.
fuente
En realidad, esta es una pregunta recurrente cuando se escriben aplicaciones JavaEE que utilizan el 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 ofreció la respuesta correcta: ¡Java no tiene 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 SortedSet, 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 usando un Comparador (o usando su orden "natural").
Pero, en cambio, está más cerca de un LinkedHashSet (que otros también sugirieron), o más aún de un (también inexistente) "ArrayListSet", porque garantiza que los elementos se devuelven en el mismo orden en que se insertaron.
¡Pero 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 tengan un orden específico y sin duplicados, y luego crear una instancia con cualquier implementación (por ejemplo, una implementación proporcionada por Hibernate).
Como JDK es de código abierto, tal vez esta interfaz finalmente se incluirá en Java 7 ...
fuente
ListOrderedSet
lo que el OP necesitaba hace 7 años (y yo necesitaba hoy).What is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList)...
e ignoré...interface
. ¡Lo siento por eso!Solo agrego un punto que no fue mencionado en la respuesta de mmyers .
También debe familiarizarse con la
SortedSet
interfaz (cuya implementación más común esTreeSet
).Un conjunto ordenado es un conjunto (es decir, los elementos son únicos) que se mantiene ordenado por el orden natural de los elementos o por el uso de algunos
Comparator
. Puede acceder fácilmente al primer y último elemento utilizandofirst()
ylast()
métodos. ASortedSet
es útil de vez en cuando, cuando necesita mantener su colección libre de duplicados y ordenada de cierta manera.Editar : si necesita un conjunto cuyos elementos se mantienen en orden de inserción (al igual que una lista), eche un vistazo
LinkedHashSet
.fuente
Este tipo de pregunta lleva a la pregunta de cuándo debe usar un conjunto y cuándo debe usar una lista. Por lo general, el consejo es:
Un cuarto caso que aparece a menudo es que no necesita ninguno. En este caso, verá que algunos programadores van con listas y otros con conjuntos. Personalmente, me resulta muy dañino verlo como una lista sin ordenar, porque es realmente una bestia completamente diferente. A menos que necesite cosas como establecer unicidad o establecer igualdad, siempre favorezca las listas.
fuente
No estoy seguro de si alguien lo ha explicado exactamente de esta manera, pero debe comprender lo siguiente:
No hay un "primer" elemento en un conjunto.
Porque, como han dicho otros, los conjuntos no tienen orden. Un conjunto es un concepto matemático que específicamente no incluye la ordenación.
Por supuesto, su computadora realmente no puede mantener una lista de cosas que no están ordenadas en la memoria. Tiene que tener algunos pedidos. Internamente es una matriz o una lista vinculada o algo así. Pero realmente no sabes lo que es, y realmente no tiene un primer elemento; el elemento que sale "primero" sale de esa manera por casualidad, y podría no ser el primero la próxima vez. Incluso si tomaste medidas para "garantizar" un primer elemento en particular, todavía sale por casualidad, porque acabas de acertar para una implementación particular de un Set; una implementación diferente podría no funcionar de esa manera con lo que hizo. Y, de hecho, es posible que no conozca la implementación que está utilizando tan bien como cree.
La gente se encuentra con este TODO. EL. HORA. con sistemas RDBMS y no entiendo. Una consulta RDBMS devuelve un conjunto de registros. Este es el mismo tipo de conjunto de 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í y luego se tropieza algún día cuando la forma de sus datos o código cambia ligeramente y activa el optimizador de consultas para que funcione de una manera diferente y de repente los resultados no salen en el orden que esperan. Estas son típicamente las personas que no prestaron atención en la clase de 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 pedido garantizado.
fuente
Set
esIterable
.faltan algunas estructuras de datos en 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, puede estar interesado en Google Collections
fuente
Es cierto, los elementos en Set no están ordenados, por definición de Set Collection. Por lo tanto, 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 sea igual al que estamos buscando? De esta manera, podemos acceder a los datos del elemento dentro del Conjunto, simplemente conociendo sus atributos utilizados por el método de igualdad.
fuente
Si va a hacer muchos accesos aleatorios por índice en un conjunto, puede obtener una vista de matriz de sus elementos:
Sin embargo, hay dos inconvenientes principales:
fuente
Esto se debe a que Set solo garantiza la unicidad, 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.
fuente
La única razón por la que puedo pensar para usar un índice numérico en un conjunto sería para la iteración. Para eso, usa
fuente
Me encontré con situaciones en las que realmente quería un Sorted Conjunto con acceso a través de índice (Estoy de acuerdo con otros críticos que se accede a un conjunto sin clasificar con un índice que no tiene sentido). Un ejemplo sería un árbol donde quisiera que se clasificaran los niños y no se permitieran duplicarlos.
Necesitaba el acceso a través del índice para mostrarlos y los atributos establecidos fueron útiles para eliminar eficientemente los duplicados.
Al no encontrar una colección adecuada en java.util o en las colecciones de google, me resultó sencillo implementarla yo mismo. La idea básica es envolver un SortedSet y crear una Lista cuando se requiere acceso a través del índice (y olvidar la lista cuando se cambia el SortedSet). Por supuesto, esto solo funciona de manera eficiente cuando se cambia el SortedSet envuelto 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, este rendimiento mejoró mucho en una lista que mantuve ordenada a través de Collections.sort.
fuente
Tenga en cuenta que solo se puede acceder a 2 estructuras de datos básicas a través del índice.
O(1)
complejidad de tiempo para lograr laget(int index)
operación.O(n)
complejidad de tiempo para lograr laget(int index)
operación.En Java,
ArrayList
se implementa utilizando la estructura de datos Array .Si bien la estructura de datos de Set generalmente se puede implementar a través de la estructura de datos HashTable / HashMap o BalancedTree , para detectar rápidamente si un elemento existe y agregar un elemento no existente, generalmente un Set bien implementado puede lograr una operación de
O(1)
complejidad de tiempocontains
. En Java,HashSet
es la implementación más utilizada de Set , se implementa llamando a laHashMap
API yHashMap
se implementa mediante un encadenamiento separado con listas vinculadas (una combinación de Array y LinkedList ).Dado que Set se puede implementar a través de una estructura de datos diferente, no hay ningún
get(int index)
método para ello.fuente
Data.Sequence.lookup
función de Haskell ) también permiten acceder a través del índice (O(1)
cerca de los extremosO(log n)
cerca del centro, con mayor precisiónO(min(log(k), log(n-k)))
), también lo hacen los árboles binarios (consulte laData.Set.lookupIndex
función de Haskell ). Por lo tanto, su afirmación inicial de que "Tenga en cuenta que solo se puede acceder a la estructura de datos básica 2 a través del índice" no es correcta.La razón por la cual la interfaz Set no tiene una llamada get index-type o incluso algo aún más básico, como first () o last (), es porque es una operación ambigua y, por lo tanto, una operación potencialmente peligrosa. Si un método devuelve un Set y usted llama, digamos primero el método (), ¿cuál es el resultado esperado, dado que un Set genérico no garantiza el pedido? El objeto resultante bien podría variar entre cada llamada del método, o podría no hacerlo y adormecerlo con una falsa sensación de seguridad, hasta que la biblioteca que está utilizando los cambios cambie la implementación debajo y ahora descubra que todo su código se rompe por ninguna razón en particular.
Las sugerencias sobre soluciones alternativas que se enumeran aquí 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 invocaciones posteriores o con diferentes implementaciones subyacentes. Si necesita algo intermedio, un SortedSet o LinkedHashSet es lo que desea.
// Sin embargo, me gustaría que la interfaz Set tuviera un elemento get-random-element.
fuente
java.util.Set
es una colección de artículos sin ordenar. No tiene ningún sentido si el Set tiene un get (int index), porque Set no tiene un índice y también solo puedes adivinar el valor.Si realmente quiere esto, codifique un método para obtener un elemento aleatorio de Set.
fuente
Tu puedes hacer
new ArrayList<T>(set).get(index)
fuente
new ArrayList<T>(t).get(0)
creo que existe una oposición válida a la idea de obtener un elemento particular de un Conjunto por un índice. Pero sería bueno si Set tuviera una función miembro only () que, para Conjuntos de tamaño 1, proporcionara acceso fácil al único elemento en el Set. Esto salvaría lo mencionadonew ArrayList
ofor (Foo foo : foos) { return foo; }
Si no le importa ordenar el conjunto, puede interesarle echar un vistazo al proyecto de mapa de árbol indexado .
El TreeSet / TreeMap mejorado 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. Por lo tanto, no hay iteración o respaldo por una lista aquí.
fuente
Set es una interfaz y algunas de sus clases de implementación son HashSet, TreeSet y LinkedHashSet. Utiliza HashMap debajo del capó para almacenar valores. Debido a que HashMap no conserva el orden, no es posible obtener valor por índice.
Ahora debe estar pensando cómo Set está usando HashMap, ya que HashMap almacena un par clave, valor, pero el Set no. pregunta válida cuando agrega un elemento en Set, internamente, mantiene un HashMap donde la clave es el elemento que desea ingresar en Set y el valor es la constante ficticia. A continuación se muestra una implementación interna de la función de agregar. Por lo tanto, todas las claves en el HashMap tendrán el mismo valor constante.
fuente
Set
las implementaciones de s se utilizanHashMap
bajo el capó para almacenar valores, ¿ puede justificar esa afirmaciónTreeSet
?the keys in the HashMap will have the same constant value
las teclas en elHashMap
mapa se asignarán a una misma e inmutableObject
Para obtener un elemento en un conjunto, utilizo el siguiente:
fuente
T
definido? ¿Por quéif (true)
?