7
votes

Pourquoi java.util.set ne contient pas de valeur getter? Y a-t-il des alternatives?

Comme définies Les entrées sont distinguées uniquement par un sous-ensemble de propriétés ( hashcode () + égale () ), il est parfois nécessaire de fonctionner sur l'objet original contenu dans Un ensemble, qui n'est pas possible avec java.util.set . La seule alternative que j'ai proposée est: mappe - pas une solution très concise.

Y a-t-il d'autres alternatives dans le cadre de collections? Les exigences sont les suivantes: o (1) extraction du temps et aucun doublure basé sur hashcode () + est égal () résultat.


15 commentaires

Vous recherchez HASHSET ?


Ah, donc vous voulez l'objet d'origine de l'ensemble. Eh bien, la solution la plus simple serait votre carte solution. Y a-t-il une raison pour laquelle ce n'est pas très pratique?


@Kayaman - Droite, fixe


@Dhrubajyotigogoi - hashset n'est qu'une implémentation de l'ensemble


@assylias Je ne peux pas récupérer la valeur d'origine de se mettre dans O (1) heure. Est-ce-que je peux?


@Marcin Non, c'est pourquoi vous avez besoin d'un haschmap. C'est l'autre collection de hachage dans l'API standard. Et c'est la solution avec le moins d'effort. Pas une très jolie solution, mais vous n'avez pas de très jolies exigences: |


@Marcin peut être je n'ai pas été capable de comprendre votre problème. Mais avec HASHSET, vous avez à la fois une récupération de temps constante pour les opérations de base et, car elle est soutenue par des ensembles, il ne permettra pas des duplicats (basés sur HashCode () et égaux ()). Est-ce que cela ne résout pas votre problème?


@Dhrubajyotigogoi Essayez d'extraire l'objet d'origine de hashset . C'est ce que j'aimerais faire.


@Marcin Vous voulez dire une sorte de piscine de sorte que lorsque vous avez besoin d'une nouvelle instance de votre objet, vous vérifiez d'abord si un élément similaire (Equals + HashCode) existe déjà dans la collection et utilisez celui-ci si c'est le cas?


@Marcin, vous récupérerez le même objet que vous avez utilisé.


@Marvin: Quel objet voulez-vous récupérer de l'ensemble? Un ensemble peut contenir de nombreux objets et, étant donné qu'un ensemble n'a pas de commande définie, un obtenez (Int index) méthode n'a pas de sens.


@Marcin Comment envisagez-vous de récupérer l'objet original? Par quelques essences, objet avec des propriétés identiques ou l'objet d'origine lui-même ou autre chose?


Une carte est la la solution de droite.


(Aussi, FWIW, A hashmap ne prendra plus de mémoire qu'un hashset et sera exactement aussi efficace. Sérieusement.)


Je n'ai pas vraiment d'objectif de l'accès. Vous essayez d'accéder déjà à vous savoir (comme HASHCODE () + égaux () sont les mêmes) - pour des raisons de curiosité, pourriez-vous expliquer ce que cela est nécessaire?


7 Réponses :


0
votes

pas dans java.util.collections elle-même, mais en utilisant Google Guava , vous pouvez récupérer n'importe quel élément à partir d'un itérateur en utilisant itérables.get .

Normalement, je ne ferais pas préconiser les bibliothèques externes, mais étant donné à quel point Guava est extrêmement puissant et utile, je ne vois aucun problème avec cela.

Alternativement, vous pouvez simplement itérer l'ensemble avec votre propre implémentation.


En outre, j'ai trouvé un très intéressant thread ici qui explique ce comportement.


1 commentaires

Mais ce ne serait plus O (1).



0
votes

A SET ne peut pas contenir deux objets O1 et O2 tel que o1.equals (O2 ) (non hashcode est utilisé dans ce critère).

A HashSet utilise un hashmap pour stocker efficacement ses objets afin que ce soit éventuellement un hashmap est exactement ce dont vous avez besoin pour HashCode () + Equals () Opérations basées.


4 commentaires

Ce n'est pas ce qu'il demande: il souhaite récupérer un objet d'un ensemble que est égal à un autre objet en temps constant.


@arshajii Je comprends que, mais l'interface Set ne fournit pas la méthode d'obtention de récupération des objets et son probablement, car ce n'est pas l'intention d'un ensemble. Son exigence de distinguer efficacement des objets en utilisant leur hachage et ses égaux est exactement ce que font les cartes de hachage.


Donc, vous dites qu'il devrait utiliser une carte , comme il l'a déjà tenté?


Cela dépend vraiment de ce qu'il veut dire par objet d'origine. Cela fait-il référence à la même instance créée (Memory-Wise) ou juste un objet avec les mêmes propriétés. Pour ce dernier, il peut utiliser en toute sécurité un hashmap. Et j'aimerais vraiment savoir quel est le besoin du même cas exact si tel est le cas.



0
votes

J'ai écrit une telle classe si vous voulez le réutiliser. Jayes contient une classe org.eclipse.recommenders.jayes.util.sharing.canonicalset Cela permet de récupérer à peu près toutes les relations d'équivalence que vous pouvez encoder dans un hashcode () et égale () implémentation. Je l'ai utilisé pour construire des cours d'équivalence de tableau. Vous pouvez examiner ces implémentations de canonicalset , ils sont dans le même package.

Oh, mais oui, il est également basé sur une carte , t> , donc rien de magique vraiment.


0 commentaires

0
votes

Le code d'un hashset basé sur un hashmap est super simple: si vous regardez la façon dont il est implémenté dans la JDK, il existe très peu de lignes de code réel (ignorant les constructeurs et la sérialisiazation Code).

Entraînant pour le faire, il serait de mettre en œuvre votre propre version de hashset avec le supplémentaire () méthode xxx


0 commentaires

0
votes

Vous pouvez utiliser setuniquelist de collections Commons

Il décore un java.util.list Pour vous assurer qu'aucun doublure n'est présent comme un java.util.set . .


0 commentaires

0
votes

Oui, il s'agit d'un peu de douleur, de ne pas pouvoir partager forte> objets égaux. Le problème avec l'API fixé, il manque un SPÉCIFICADGET:

private Map<T, T> sharedThings = new HashMap<>().

public T shareThing(T s) {
    String t = sharedThings.get(s);
    if (t == null) {
        t = s;
        sharedStrings.put(t, t);
    }
    return t;
}

...

public void setT(T t) {
    this.t = sharedThing(t);
}


0 commentaires

2
votes

Si une opération supplémentaire O (1) n'est pas un problème, vous pouvez Simuler Absence de méthode Obtenir (objet) avec une paire de méthodes set.remove (objet ) et set.add (objet) . Sinon, j'utiliserais mapper comme vous l'avez mentionné ou simple classe wrapper avec une carte sous-jacente.

edit : la raison pour laquelle définir ne contient pas obtenez (objet) est-ce que vous n'avez pas besoin de retourner objet que vous n'avez pas besoin de renvoyer l'objet que vous avez connaître. Il vous suffit de vérifier si votre objet est contenu dans Définir ou non.


0 commentaires