J'ai vu d'autres questions sur l'obtention d'objets à partir de Set
en fonction de la valeur d'index et je comprends pourquoi ce n'est pas possible. Mais je n'ai pas été en mesure de trouver une bonne explication de la raison pour laquelle un objet obtenu par l'objet n'est pas autorisé, alors je me suis posé la question.
HashSet
est soutenu par un HashMap
, donc en obtenir un objet devrait être assez simple. Dans l'état actuel des choses, il me semble que je devrais parcourir chaque élément de la variable HashSet
et tester l'égalité, ce qui semble inutile.
Je pourrais simplement utiliser un Map
mais je n'ai pas besoin d'une clé: paire de valeurs, j'ai juste besoin d'un Set
.
Par exemple, disons que j'ai Foo.Java
:
package example;
import Java.io.Serializable;
public class Foo implements Serializable {
String _id;
String _description;
public Foo(String id){
this._id = id
}
public void setDescription(String description){
this._description = description;
}
public String getDescription(){
return this._description;
}
public boolean equals(Object obj) {
//equals code, checks if id's are equal
}
public int hashCode() {
//hash code calculation
}
}
et Example.Java
:
package example;
import Java.util.HashSet;
public class Example {
public static void main(String[] args){
HashSet<Foo> set = new HashSet<Foo>();
Foo foo1 = new Foo("1");
foo1.setDescription("Number 1");
set.add(foo1);
set.add(new Foo("2"));
//I want to get the object stored in the Set, so I construct a object that is 'equal' to the one I want.
Foo theFoo = set.get(new Foo("1")); //Is there a reason this is not allowed?
System.out.println(theFoo.getDescription); //Should print Number 1
}
}
Est-ce parce que la méthode equals est conçue pour tester l'égalité "absolue" plutôt que l'égalité "logique" (auquel cas contains(Object o)
serait suffisant)?
Set
est une Collection
d'objets qui traite a.equals(b) == true
en tant que doublons, il est donc inutile d'essayer d'obtenir le même objet que vous avez déjà.
Si vous essayez de get(Object)
à partir d'une collection, une Map
sera probablement plus appropriée.
Ce que tu devrais écrire c'est
Map<String, String> map = new LinkedHashMap<>();
map.put("1", "Number 1");
map.put("2", null);
String description = set.get("1");
si un objet n'est pas dans l'ensemble (basé sur égaux), ajoutez-le, s'il est dans l'ensemble (basé sur égaux) donnez-moi l'instance de cet objet de l'ensemble
Dans le cas peu probable où vous en aurez besoin, vous pouvez utiliser une Map
.
Map<Bar, Bar> map = // LinkedHashMap or ConcurrentHashMap
Bar bar1 = new Bar(1);
map.put(bar1, bar1);
Bar bar1a = map.get(new Bar(1));
Java Map/Aide-mémoire de collection
Contiendra-t-il une paire clé/valeur ou des valeurs uniquement?
1) S'il contient pairs, le choix est une carte. L'ordre est-il important?
. 1-1) Si yes, suivez l'ordre d'insertion ou triez les clés?
. . 1-1-1) Si commandé, LinkedHashMap
. . 1-1-2) Si trié, TreeMap
. 1-2) Si l'ordre est pas important, HashMap
2) S'il ne stocke que values , le choix est une collection. Contiendra-t-il des doublons?
. 2-1) Si yes, ArrayList
. 2-2) S'il y a pas des doublons, la tâche principale consiste à rechercher des éléments (contient/supprime)?
. . 2-2-1) Si no, ArrayList
. . 2-2-2) Si oui, l'ordre est-il important?
. . . 2-2-2-1) Si l'ordre est pas important, HashSet
. . . 2-2-2-2) Si yes, suivez l'ordre d'insertion ou triez par valeurs?
. . . . 2-2-2-2-1) si commandé, LinkedHashSet
. . . . 2-2-2-2-2) si triés, TreeSet
Votre dernière phrase est la réponse.
get(Object o)
parcourrait la HashSet
à la recherche d'un autre objet égal à o
(avec la méthode equals(o)
). Donc, il s’agit bien de contains(o)
, mais ne renvoie pas le même résultat.
Si vous voulez savoir que l'objet new Foo("1");
est déjà présent dans la set
, vous devez utiliser la méthode contains
comme:
boolean present = set.contains(new Foo("1"));
Le type de méthode get
c'est-à-dire set.get(new Foo("1"));
n'est pas pris en charge car cela n'a aucun sens. Vous avez déjà l'objet, c'est-à-dire new Foo("1")
, puis quelles informations supplémentaires vous rechercheriez via la méthode get
.
La raison pour laquelle il n'y a pas de get est simple:
Si vous devez extraire l'objet X de l'ensemble, c'est parce que vous avez besoin de quelque chose de X et que vous n'avez pas cet objet.
Si vous n’avez pas l’objet, vous avez besoin d’un moyen (clé) pour le localiser. ..its name, un nombre quoi que jamais. C'est ce que les cartes sont pour le bien.
map.get ("clé") -> X!
Les ensembles n'ont pas de clés, vous devez les traverser pour récupérer les objets.
Alors, pourquoi ne pas ajouter un get pratique get (X) -> X
Cela n’a aucun sens, car vous avez déjà X, dira le puriste.
Mais maintenant, considérez-le comme non puriste et voyez si vous voulez vraiment ceci:
Supposons que je crée l'objet Y, qui correspond aux égaux de X, de sorte que set.get (Y) -> X. Volia, alors je peux accéder aux données de X que je n'avais pas. Disons par exemple que X a une méthode appelée get flag () et que j'en veux le résultat.
Maintenant, regardez ce code.
Y
X = map.get (Y);
Donc Y.equals (x) vrai!
mais..
Y.flag () == X.flag () = false. (N'étaient-ils pas égaux?)
Donc, voyez-vous, si cela vous permettait d’obtenir les objets comme celui-ci, c’est sûrement de casser la sémantique de base des égaux. Plus tard, vous allez vivre avec de petits clones de X, tous affirmant qu'ils sont identiques quand ils ne le sont pas.
Vous avez besoin d'une carte pour stocker des éléments et utiliser une clé pour les récupérer.
si vous voulez seulement savoir ce qu'il y a dans le hachage, vous pouvez utiliser la méthode .toString();
pour afficher tout le contenu du hachage séparé par une virgule.
HashSet est un peu plus simple que HashMap. Si vous n'avez pas besoin des fonctionnalités de HashMap, pourquoi l'utiliser? Si la méthode comme getObject (ObjectType o) a été implémentée par Java, il n'est pas nécessaire de parcourir l'ensemble après l'appel de la méthode contain ()