Je suis sûr qu'il y a une bonne raison, mais quelqu'un pourrait-il expliquer pourquoi l' java.util.Set
interface manque get(int Index)
ou toute autre get()
méthode similaire ?
Il semble que les ensembles soient parfaits pour y mettre des choses, mais je ne trouve pas un moyen élégant de récupérer un seul élément de celui-ci.
Si je sais que je veux le premier élément, je peux l'utiliser set.iterator().next()
, mais sinon, il semble que je doive effectuer un cast vers un tableau pour récupérer un élément à un index spécifique?
Quels sont les moyens appropriés pour récupérer des données d'un ensemble? (autre que l'utilisation d'un itérateur)
Je suis sûr que le fait qu'il soit exclu de l'API signifie qu'il y a une bonne raison de ne pas le faire - quelqu'un pourrait-il m'éclairer?
EDIT: Quelques réponses extrêmement excellentes ici, et quelques-unes disant "plus de contexte". Le scénario spécifique était un test dbUnit, où je pouvais raisonnablement affirmer que l'ensemble renvoyé d'une requête n'avait qu'un seul élément, et j'essayais d'accéder à cet élément.
Cependant, la question est plus valable sans le scénario, car elle reste plus ciblée:
Quelle est la différence entre set et list .
Merci à tous pour les réponses fantastiques ci-dessous.
la source
Réponses:
Parce que les ensembles n'ont pas de commande. Certaines implémentations le font (en particulier celles implémentant l'
java.util.SortedSet
interface), mais ce n'est pas une propriété générale des ensembles.Si vous essayez d'utiliser des ensembles de cette façon, vous devriez plutôt utiliser une liste.
la source
En fait, c'est une question récurrente lors de l'écriture d'applications JavaEE qui utilisent le mappage relationnel objet (par exemple avec Hibernate); et parmi toutes les personnes qui ont répondu ici, Andreas Petersson est le seul à avoir compris le vrai problème et à lui proposer la bonne réponse: il manque une UniqueList à Java! (ou vous pouvez également l'appeler OrderedSet ou IndexedSet).
Maxwing a mentionné ce cas d'utilisation (dans lequel vous avez besoin de données commandées ET uniques) et il a suggéré le SortedSet, mais ce n'est pas ce dont Marty Pitt avait vraiment besoin.
Cet "IndexedSet" n'est PAS le même qu'un SortedSet - dans un SortedSet les éléments sont triés en utilisant un comparateur (ou en utilisant leur ordre "naturel").
Mais au lieu de cela, il est plus proche d'un LinkedHashSet (que d'autres ont également suggéré), ou encore plus d'un "ArrayListSet" (également inexistant), car il garantit que les éléments sont retournés dans le même ordre qu'ils ont été insérés.
Mais le LinkedHashSet est une implémentation, pas une interface! Ce dont nous avons besoin, c'est d'une interface IndexedSet (ou ListSet, OrderedSet ou UniqueList)! Cela permettra au programmeur de spécifier qu'il a besoin d'une collection d'éléments qui ont un ordre spécifique et sans doublons, puis de l'instancier avec n'importe quelle implémentation (par exemple une implémentation fournie par Hibernate).
Étant donné que JDK est open-source, cette interface sera peut-être finalement incluse dans Java 7 ...
la source
ListOrderedSet
ce dont le PO avait besoin il y a 7 ans (et j'avais besoin aujourd'hui).What is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList)...
et ignoré...interface
. Désolé pour ça!J'ajoute juste un point qui n'a pas été mentionné dans la réponse de mmyers .
Vous devez également vous familiariser avec l'
SortedSet
interface (dont l'implémentation la plus courante estTreeSet
).Un SortedSet est un ensemble (c'est-à-dire que les éléments sont uniques) qui est maintenu ordonné par l' ordre naturel des éléments ou en utilisant certains
Comparator
. Vous pouvez facilement accéder aux premier et dernier éléments à l'aide des méthodesfirst()
etlast()
. ASortedSet
est utile de temps en temps, lorsque vous devez conserver votre collection à la fois sans doublon et commandée d'une certaine manière.Edit : Si vous avez besoin d'un ensemble dont les éléments sont conservés dans l'ordre d'insertion (un peu comme une liste), jetez un œil à
LinkedHashSet
.la source
Ce type de conduit à la question de savoir quand vous devez utiliser un ensemble et quand vous devez utiliser une liste. Habituellement, le conseil va:
Un quatrième cas qui apparaît souvent est que vous n'avez besoin ni de l'un ni de l'autre. Dans ce cas, certains programmeurs utilisent des listes et d'autres des ensembles. Personnellement, je trouve très dangereux de voir l'ensemble sous forme de liste sans commander - car c'est vraiment une toute autre bête. Sauf si vous avez besoin de choses comme l'unicité ou l'égalité définies, privilégiez toujours les listes.
la source
Je ne sais pas si quelqu'un l'a expliqué exactement de cette façon, mais vous devez comprendre ce qui suit:
Il n'y a pas de "premier" élément dans un ensemble.
Parce que, comme d'autres l'ont dit, les ensembles n'ont pas de commande. Un ensemble est un concept mathématique qui n'inclut pas spécifiquement la commande.
Bien sûr, votre ordinateur ne peut pas vraiment garder une liste de choses qui ne sont pas commandées en mémoire. Il doit y avoir une certaine commande. En interne, c'est un tableau ou une liste chaînée ou quelque chose. Mais vous ne savez pas vraiment ce que c'est, et il n'a pas vraiment de premier élément; l'élément qui sort «premier» sort de cette façon par hasard, et pourrait ne pas être le premier la prochaine fois. Même si vous avez pris des mesures pour «garantir» un premier élément particulier, il sort toujours par hasard, parce que vous vous êtes avéré qu'il était juste de le faire pour une implémentation particulière d'un ensemble; une implémentation différente peut ne pas fonctionner de cette façon avec ce que vous avez fait. Et, en fait, vous ne connaissez peut-être pas aussi bien l'implémentation que vous utilisez.
Les gens se heurtent à tout cela. LES. TEMPS. avec les systèmes SGBDR et ne comprennent pas. Une requête SGBDR renvoie un ensemble d'enregistrements. Il s'agit du même type d'ensemble issu des mathématiques: une collection d'éléments non ordonnée, dans ce cas uniquement, les éléments sont des enregistrements. Un résultat de requête SGBDR n'a aucun ordre garanti du tout, sauf si vous utilisez la clause ORDER BY, mais tout le temps les gens le supposent, puis se déclenchent un jour lorsque la forme de leurs données ou de leur code change légèrement et déclenche l'optimiseur de requête pour fonctionner d'une manière différente et tout à coup les résultats ne sortent pas dans l'ordre qu'ils attendent. Ce sont généralement les personnes qui n'ont pas fait attention dans la classe de base de données (ou lors de la lecture de la documentation ou des didacticiels) lorsqu'il leur a été expliqué, à l'avance, que les résultats de la requête n'ont pas un ordre garanti.
la source
Set
estIterable
.certaines structures de données manquent dans les collections Java standard.
Sac (comme l'ensemble mais peut contenir des éléments plusieurs fois)
UniqueList (liste ordonnée, ne peut contenir chaque élément qu'une seule fois)
semble que vous auriez besoin d'une liste unique dans ce cas
si vous avez besoin de structures de données flexibles, vous pourriez être intéressé par Google Collections
la source
C'est vrai, les éléments de Set ne sont pas ordonnés, par définition de la collection Set. Ils ne peuvent donc pas être accessibles par un index.
Mais pourquoi n'avons-nous pas une méthode get (object), non pas en fournissant l'index comme paramètre, mais un objet qui est égal à celui que nous recherchons? De cette façon, nous pouvons accéder aux données de l'élément à l'intérieur de l'ensemble, simplement en connaissant ses attributs utilisés par la méthode égale.
la source
Si vous allez faire beaucoup d'accès aléatoires par index dans un ensemble, vous pouvez obtenir une vue tableau de ses éléments:
Il existe cependant deux inconvénients principaux:
la source
En effet, Set garantit uniquement l'unicité, mais ne dit rien sur les modèles d'accès ou d'utilisation optimaux. C'est-à-dire qu'un ensemble peut être une liste ou une carte, chacune ayant des caractéristiques de récupération très différentes.
la source
La seule raison pour laquelle je peux penser à utiliser un index numérique dans un ensemble serait pour l'itération. Pour cela, utilisez
la source
Je courus dans des situations où je voulais en fait un Sorted Set avec accès par index (je suis d' accord avec d' autres affiches que l' accès à un ensemble non triés avec un indice n'a pas de sens). Un exemple serait un arbre où je voulais que les enfants soient triés et les enfants en double n'étaient pas autorisés.
J'avais besoin de l'accès via un index pour les afficher et les attributs définis étaient utiles pour éliminer efficacement les doublons.
Ne trouvant aucune collection appropriée dans les collections java.util ou google, je l'ai trouvé simple à implémenter moi-même. L'idée de base est d'envelopper un SortedSet et de créer une liste lorsque l'accès via un index est requis (et d'oublier la liste lorsque le SortedSet est modifié). Bien entendu, cela ne fonctionne efficacement que lorsque vous modifiez le SortedSet encapsulé et que l'accès à la liste est séparé pendant la durée de vie de la collection. Sinon, il se comporte comme une liste triée souvent, c'est-à-dire trop lente.
Avec un grand nombre d'enfants, cette performance a été améliorée par rapport à une liste que j'ai gardée triée via Collections.sort.
la source
Veuillez noter que seules 2 structures de données de base sont accessibles via l'index.
O(1)
complexité temporelle pour réaliser l'get(int index)
opération.O(n)
complexité temporelle pour réaliser l'get(int index)
opération.En Java,
ArrayList
est implémenté à l'aide de la structure de données Array .Bien que Définir la structure de données peut généralement être mis en œuvre par l' intermédiaire Hashtable / HashMap ou BalancedTree structure de données, pour détecter rapidement si un élément existe et ajoutez élément non existant, généralement un bien mis en œuvre ensemble peut atteindre la
O(1)
complexité du tempscontains
fonctionnement. En Java,HashSet
est l'implémentation la plus couramment utilisée de Set , elle est implémentée en appelant l'HashMap
API etHashMap
est implémentée en utilisant un chaînage séparé avec des listes liées (une combinaison d' Array et LinkedList ).Puisque Set peut être implémenté via une structure de données différente, il n'y a pas de
get(int index)
méthode pour cela.la source
Data.Sequence.lookup
fonction de Haskell ) permettent également d'accéder via un index (O(1)
près des extrémitésO(log n)
près du milieu, plus précisémentO(min(log(k), log(n-k)))
), ainsi que les arbres binaires (voir laData.Set.lookupIndex
fonction de Haskell ). Votre affirmation initiale selon laquelle "Veuillez noter que seules 2 structures de données de base sont accessibles via l'index" n'est pas correcte.La raison pour laquelle l' interface Set n'a pas d'appel get de type index ou même quelque chose de plus basique, comme first () ou last (), c'est parce que c'est une opération ambiguë, et donc potentiellement dangereuse. Si une méthode retourne un Set, et que vous appelez, disons la méthode first () dessus, quel est le résultat attendu, étant donné qu'un Set générique ne fait aucune garantie sur la commande? L'objet résultant pourrait très bien varier entre chaque appel de la méthode, ou il pourrait ne pas vous endormir dans un faux sentiment de sécurité, jusqu'à ce que la bibliothèque que vous utilisez modifie l'implémentation ci-dessous et maintenant vous constatez que tout votre code se casse pour sans raison particulière.
Les suggestions de solutions de contournement répertoriées ici sont bonnes. Si vous avez besoin d'un accès indexé, utilisez une liste. Soyez prudent avec l'utilisation d'itérateurs ou toArray avec un ensemble générique, car a) il n'y a aucune garantie sur l'ordre et b) il n'y a aucune garantie que l'ordre ne changera pas avec les invocations suivantes ou avec différentes implémentations sous-jacentes. Si vous avez besoin de quelque chose entre les deux, un SortedSet ou un LinkedHashSet est ce que vous voulez.
// Je souhaite cependant que l'interface Set ait un élément get-random-element.
la source
java.util.Set
est une collection d'articles non commandés. Cela n'a aucun sens si l'ensemble a un get (int index), car l'ensemble n'a pas d'index et vous ne pouvez que deviner la valeur.Si vous le voulez vraiment, codez une méthode pour obtenir un élément aléatoire de Set.
la source
Tu peux faire
new ArrayList<T>(set).get(index)
la source
new ArrayList<T>(t).get(0)
je pense qu'il y a une opposition valable à l'idée d'obtenir un élément particulier d'un ensemble par un index. Mais ce serait bien si Set avait une fonction membre only () qui, pour les Sets de taille 1, permettait d'accéder facilement au seul élément du Set. Cela sauverait ce qui précèdenew ArrayList
oufor (Foo foo : foos) { return foo; }
Si cela ne vous dérange pas que l'ensemble soit trié, vous serez peut-être intéressé par le projet d' index-tree-map .
TreeSet / TreeMap amélioré permet d'accéder aux éléments par index ou en obtenant l'index d'un élément. Et l'implémentation est basée sur la mise à jour des poids des nœuds dans l'arborescence RB. Donc pas d'itération ni de sauvegarde par une liste ici.
la source
Set est une interface et certaines de ses classes d'implémentation sont HashSet, TreeSet et LinkedHashSet. Il utilise HashMap sous le capot pour stocker les valeurs. Étant donné que HashMap ne conserve pas l'ordre, il n'est pas possible d'obtenir la valeur par index.
Vous devez maintenant penser à la façon dont Set utilise HashMap car HashMap stocke une paire clé / valeur, mais pas Set. question valable. lorsque vous ajoutez un élément dans Set, en interne, il conserve un HashMap où la clé est l'élément que vous souhaitez entrer dans Set et la valeur est la constante fictive. Vous trouverez ci-dessous une implémentation interne de la fonction d'ajout. Par conséquent, toutes les clés du HashMap auront la même valeur constante.
la source
Set
les implémentations s utilisentHashMap
sous le capot pour stocker des valeurs pouvez-vous justifier cette affirmationTreeSet
?the keys in the HashMap will have the same constant value
les clés duHashMap
testament correspondent à une seule et même immuableObject
Pour obtenir un élément dans un ensemble, j'utilise le suivant:
la source
T
défini? Pourquoiif (true)
?